The HTML5 details Element
Warning: This article is currently intentionally verbose. That is because I am seeking feedback on my approach to the problem I am attempting to solve, particularly in the area of my approach to accessibility.
The HTML5 details element is one of my personal favorite additions to the HTML specification. Why? It provides an often used interactive function that when supported works even with JavaScript disabled.
There are many reasons why content may need to be hidden from the user until the user decides they want to see the content and interacts with the web page to say so.
Traditionally this is accomplished with JavaScript. There are however many reasons why a user may be surfing the web with JavaScript disabled. This new element provides a means to allow the user to benefit from interactive web design even if JavaScript is disabled.
Description of the details Element
The details element is a container element and must contain a summary element as its first child node. The contents of the summary element are always presented to user (unless the parent details element itself is hidden.)
All other child nodes within the details container are only presented to the user if the details element has an open attribute.
Clicking on the contents of the summary element toggles whether or not the parent details element has the attribute. If the user has JavaScript enabled, other actions may also toggle whether or not the details element has the open attribute.
Example:
<details> <summary>Detailed information on Jabberwocky</summary> <p>From <a href="http://en.wikipedia.org/wiki/Jabberwocky">Wikipedia</a>:<br/> “Jabberwocky” is a nonsense verse poem written by Lewis Carroll in his 1872 novel Through the Looking-Glass, and What Alice Found There, a sequel to Alice’s Adventures in Wonderland.</p> </details>
In the above example, since the details element does not have an open attribute, the user would only see “Detailed information on Jabberwocky” until they clicked on that summary.
Once the user clicked on the summary, the user agent (browser) would add the open attribute and show the user the rest of the content.
I think it is über cool that that kind of functionality can be made available without the need for JavaScript. It seems that most web developers get excited about the cool new scripting capabilities of JavaScript that the HTML5 spec is normalizing (canvas, CORS, etc.) but for me, it is the interactive capabilities HTML5 provides without the need to script that get me really excited (details, audio, video, etc.)
Perhaps it is because I am one of those weirdos who gets fed up with hover ads and other naughty things done with JavaScript so I frequently surf the web with JavaScript completely disabled or severely restricted.
Potential Uses of the details Node
This feature can and undoubtedly will be used in ways that I have not even thought of. The W3C documentation has an interesting figure showing potential use with a file description, including control options embedded within details. see Figure 1.
I personally use the element on some web sites for a Works Cited page where I provide more information on academic references in some web articles I have authored. See Figure 2.
Other ways in which I have used details include editorial notes in stories I am working on, to allow people reviewing them to see notes about content that I have myself, work I recognize needs to be done, etc.
Movie and Book reviews that may include spoilers the reader may not want to see is another possible use. Potential uses for this interactive element are endless.
Browser Support
The HTML5 specification is not yet finalized. Some interactive features of HTML5 (e.g. audio and video) are fairly well supported by most modern web browsers and have easy fallback to plug-in based alternatives where they are not supported.
however it appears that only the Google Chrome browser has actual support for the details element. Their current implementation has some accessibility issues. Specifically, if the details element is in a closed state, Chrome does not provide a means by which the element can be expanded without the use of a mouse.
Even though one of the beauties of the element is that when supported, JavaScript does not need to be enabled to use it, the lack of current browser support means the element probably should only be used if JavaScript is used to provide the same functionality to browsers that do not currently support it.
With proper JavaScript emulation of the details functionality, content providers can use the element now and know that the intended effect will occur for most users even before most web browsers have proper support for the element.
There is the problem of users who do not have JavaScript enabled. Those users will not get the intended effect unless their browser has native support, but there is nothing you can do for those users. Without requiring form data and page reloads, there is no way to make content selectively rendered for them.
Using the details element in your code when your design calls for selectively available content will at least work for users who do have JavaScript enabled and a growing number of users with JavaScript disabled as actual implementation of the feature grows.
Goals for JS details Emulation
My emulation of the details element is not yet complete. The following list of goals are what I wish to have accomplished before I call it done:
- Identical functionality of the Google Chrome implementation in every web browser that supports DOM2 JavaScript and CSS 2.1. This includes nesting of the details element.
- No additional markup should be required by the content author. No assumption that the id attribute will be available, etc.
- Emulation should be fully accessible for users who have a disability affecting their use of a web browser.
- Emulation should not modify the page DOM if the browser already supports details except to provide accessibility where necessary.
- JavaScript should be clean by JSLint standards.
- JavaScript should work in CSP environments that forbid use of the style attribute.
- Modifications to the page DOM should conform to W3C HTML5 specification.
These goals will be met by using a combination of minimal external CSS, DOM2 JavaScript, and the jQuery library.
External CSS is needed to avoid use of the style attribute, which is forbidden in some environments for security reasons.
jQuery is a large JavaScript library and using it for this task may seem like un-necessary bloat, but it is used because it is a JavaScript library that I personally frequently use and is thus likely to be loaded by the browser on any page I personally script for anyway.
Even with JQuery loaded, when creating a DOM element that is intended to replace an element already in the page DOM, I prefer to use straight up DOM2 JavaScript to create the element. The issue is every modification to the page DOM requires the user agent to reload the DOM to see if it needs to alter rendering. By creating the element un-attached to the page DOM, in theory anyway (I might be wrong about this) I can reduce the number of DOM refreshes the user agent has to perform during execution of the script.
When modifying existing elements already attached to the DOM, I do typically use jQuery.
Basic DOM Structure
The basic DOM structure of the emulation takes a standard details element:
<details attributes="det. atts"> <summary attributes="sum. atts">Some Summary</summary> <!-- content to be toggled --> </details>
It modifies the DOM to produce the following:
<div attributes="det. atts"> <p attributes="mod. sum. atts">Some Summary</p> <div class="class to toggle display"> <!-- content to be toggled --> </div> </div>
Any attributes that the original details element had will be present in the top level div element of the emulation. If the original details element has an open attribute, the state of the details element will be taken into consideration but the attribute will not be presented in the div element as it is meaningless there and is not a valid attribute for a div node.
Any attributes that the original summary element had will be present in the very first p element, with a class added to give the correct triangle arrow indicating the state of the emulated details element. This p element has a script attached to the click event that toggles the presentation of the content.
The child div element contains the content that is to be shown or hidden upon user interaction.
Accessibility
I have a disability. My disability does not interfere with my use of a computer, but it does interfere with other things that most people in an an industrialized nation take for granted.
It can be frustrating for people who have a disability to be dependent upon others. That frustration is heightened when the only reason dependence upon others is necessary is because simple steps were not taken to ensure the resource was properly accessible.
The ADA helps some people with disabilities gain some independence. For example, most businesses must have wheel chair access and restroom facilities that accommodate people in a wheel chair. Public transportation systems must have wheel chair lifts and seating reserved for people who are not able to stand. Public services like the Department of Motor Vehicles or a court house must have a signing interpreter available for those who can not or have difficulty hearing.
Unfortunately much of the World Wide Web is not properly accessible for people who have disabilities using a computer in a normal fashion.
If you are a web designer or web application developer, I believe it is your responsibility to take the necessary steps to ensure your content is properly accessible to as many people as possible. If you are not an application developer but provide web content using a web application designed by someone else, it is your responsibility to research the accessibility of the web application you choose to deliver your content.
The ADA may or may not not require it for your web site, but it is the right thing to do.
Making your web resources properly accessible not only is of great benefit to those who have a disability impacting their ability to use a computer the same way as someone without that disability, it also often benefits your Search Engine Optimization and frequently makes your web resource easier to use even for people without any disabilities.
All that being said, I must confess that I have only recently started digging deeper into what proper accessibility involves. Emulation of details is my first attempt at properly accessible JavaScript, and I want to get it right.
Attributes for Assistive Technology
One important aspect of proper accessibility is to ensure that the markup is done in such a way that assistive technology can properly interpret the markup.
In the case of details emulation, there are three main concerns.
The first concern is that the assistive technology needs to know that the p element being used to emulate a summary element is an object with an action associated with it when it is clicked, or the assistive equivalent of clicked.
We can accomplish this by using the tabindex attribute. By setting tabindex="0" on the p element, we can indicate that object needs to be selectable by the user without a mouse.
The second main concern is there needs to be indication as to the status of the details element. Chrome uses a ▼ to indicate the contents of the details element have been expanded and a ▶ to indicate the node is collapsed.
To convey the same information to assistive technology, I am
using the
WAI-ARIA role and aria-pressed attributes. The role attribute is being used to indicate the
p element is a button. I have not yet
received confirmation that is the best way to do it. Conceptually
it behaves the same way as a button, if setting role="button" is
incorrect, then I need to find out what is correct.
Since the default state of a details element is to hide the non summary
content, I am using aria-pressed="false" to
indicate the closed state, equivalent to visual cue of ▶. When the details element is in an open state, aria-pressed="true"
gives the equivalent to the visual cue of ▼.
I am investigating what is the proper way to convey the same information.
The third main concern is the presentation of the information to be conveyed or hidden. In the emulation all child nodes of the details element except for the summary element are placed in a single div container that has its visibility toggled by setting a CSS class.
For the same effect to take place with assistive technology, the aria-hidden attribute is used. When set to true, assistive technology knows not to present the information.
Accessibility Beyond Attributes
In a perfect world, setting the necessary attributes to trigger assistive technology would be all that one needs to do. Unfortunately proper support for assistive technology varies by user agent.
It is not the fault of the end user that the user agent does not properly support WAI-ARIA, we must go the extra mile and make sure the solution really truly is accessible.
To test whether or not your particular browser properly supports details (native or emulated) without the use of a mouse, you can try opening the details elements within Figure 2.
The most sure fire way to make sure the details can be toggled is to create a standard HTML button element that toggles the state of the details element. I do not like creating a button element but it does the job in every environment I tried.
Traditionally, hyperlink anchors and form elements are navigable via Tab key navigation and the Enter key is interpreted as a mouse click in just about every browser. Since a button node is a form element, it does solve the problem.
Unfortunately adding a button element can interfere with intended layout. For that reason our emulation does not automatically add the button.
In order to have the button added, the content author needs to add the custom data-addbutton attribute to the details element. Please note that this attribute does not have official meaning in the HTML5 specification. The data- attribute prefix is intended for attributes that have local meaning, such as this case.
It does not matter what value you give the attribute, it just has to be there.
If the attribute is present, our JavaScript will create the button but only when the browser does not have native details support. See Figure 3 for example details elements that have the custom attribute.
When a button is asked for, the script will not set the tabindex attribute on the p element that emulates a summary element. It seemed rather pointless and a possible source of confusion to have both accessible from the tab key.
Style Sheet Classes
The following CSS classes are required for emulation of the details element:
.nodisplay { display: none; } p.dbg_detOpen:before { font-style: normal; content: "▼ "; } p.dbg_detClosed:before { font-style: normal; content: "▶ "; } /* for accessibility button - restyle as you see fit */ .summaryHighlight { background-color:yellow; } button.dbg-details { font-size: 75%; color: blue; }
The reason we define the nodisplay class instead of using the jQuery .hide() animation is because jQuery .hide() works by setting the style attribute which will not work in some CSP hardened environments.
Since we will be adding accessibility and using the WAI-ARIA attribute aria-hidden it is tempting to define the following CSS:
[aria-hidden="true"] { display: none; }
That would avoid the need to use two attributes to properly hide the content in both visual browsers and screen readers. The reason we do not do this is because there are valid reasons when a content producer may want to use the aria-hidden attribute on content that should be visually displayed while using the display:none; style on content that should be available to screen readers.
JavaScript Code
Here is the JavaScript:
Download as text: JSdetails.js
Known Current Issues
Accessibility Incomplete
No actual testing by people who depend upon assistive technologies has been done. A few simple test cases should be made.
Internet Explorer
When tested under Internet Explorer 8 on Windows XP Pro, two issues were detected.
First, Internet Explorer 8 would only render one of the triangle arrows. The other triangle error was represented by a box indicating that Internet Explorer did not know how to match the character.
My guess is that Internet Explorer does not have proper support for UTF-8 in style sheets. It probably can be resolved by specifying a character code instead of the character itself, but I have not tried yet.
Secondly, Internet Explorer always showed the contents of the emulated details element. It did not appear to be a script error, my guess is that either Internet Explorer did not like the style sheet or it applies styles in a different way than every other browser.
I will fix this issue, but I am starting to get rather sick of the amount of special handling that Internet Explorer and only Internet Explorer seems to require.
I hate to sound like such an ABM whiner, but I really wish people would just stop using that web browser. It costs a lot of money for businesses to continue to support issues that only occur with that particular browser.
Figures
Figure 1: User Interface Example
This figure not yet created.
Figure 2: Works Cited Example
Hubbs and O’Connor 2009
A Guide to the
Rattlesnakes of the United States, First Edition
Tricolor Books
Tempe, AZ
ISBN: 978-0-9754641-2-0
Lanner 1999
Conifers of
California
Cachuma Press
Los Olivos, CA
ISBN: 978-0962850530
Linkhart and White 2004
The
Trinity Alps: A Hiking and Backpacking Guide, Fourth
Edition
Wilderness Press
Berkeley, CA
ISBN: 978-0-89997-306-7
Figure 3: Accessibility Button Example
The button will only be present here with browsers that do not have native support for the details element.
Hubbs and O’Connor 2009
A Guide to the
Rattlesnakes of the United States, First Edition
Tricolor Books
Tempe, AZ
ISBN: 978-0-9754641-2-0
Lanner 1999
Conifers of
California
Cachuma Press
Los Olivos, CA
ISBN: 978-0962850530
Linkhart and White 2004
The
Trinity Alps: A Hiking and Backpacking Guide, Fourth
Edition
Wilderness Press
Berkeley, CA
ISBN: 978-0-89997-306-7
Figure 4: Nesting Example
This details element has 3 child details elements
This is first nested details element
I do not have any child details elements.
This is second nested details element
I have one child details element:
I am nested two levels deep
I also am probably an example of poorly thought out UI design. Nesting two levels deep is not recommended, at least not by me.
This is third nested details element
I do not have any child details elements.
ChangeLog
: Several major changes.
The accessibility button is no longer added when there is genuine support for details. Instead, the script adds tabindex="0" attribute and uses the onkeydown event to trigger opening and closing the details. This allowed removal of the deprecated DOMSubtreeModified event handler.
I am currently only applying the aria-pressed and role="button" attributes to the accessibility button and am no longer applying them to the emulation of the summary node even when there is not a button. I need to think about that some more, I may put it back.
Bug fix where I was neglecting to unbind event handlers before adding new event handlers.
Better logic in applying event handlers when script first run.
: Do not add title attribute to accessibility button.
: For emulation of details, added role="region" and aria-live="polite" (Suggested by Eric Eggert.)
Fixed bug causing our class on emulated summary to be over-written if original summary had a class attribute.
: Place the accessibility button before the details. That way it does not jump around with nested details and it is easy to see which summary it corresponds with.
: Highlight summary corresponding with button the mouse is over.
: Initial public release.
Feedback
Unfortunately code for the DOMBlogger feedback engine is not yet demonstration ready. It really is unfortunate because I really want feedback on this script.
I would particularly like accessibility related feedback, but I also would like feedback on the JavaScript itself.
I understand the value of JavaScript as a tool, but to be honest, I have never been that fond of it. Until I started work on the DOMBlogger CMS, I have primarily been a backen PHP and SQL guy, rarely dabbling in front end technology. If there is a better way to do any of the things the script is doing, by all means please let me know.
Until the feedback engine is complete and tested, please mail any feedback to mpeters@domblogger.net.
Alternative to e-mail, if you are a member of the Opera community, you can leave feedback in this thead.
Thank you!