Screen Readers and details/summary

The HTML5 details and summary elements can be used to create a disclosure widget for showing and hiding content, something that typically has been done with JavaScript. For example, this type of interaction has often been used for things like FAQs: a list of questions is provided, but the answers hidden; clicking on any one of the questions toggles the display of the answer below it in accordion-like fashion. Check out the HTML5 Doctor's article, "The details and summary elements", to learn more.

For straightforward details/summary pairs where the summary element contains only text, browsers and screen readers do pretty well, assuming appropriate keyboard focus and WAI-ARIA support is provided where necessary. However, where one or more links are nested in the summary, things get a little more cumbersome.

What follows is a very long and detailed account of some of the browser, screen reader, and accessibility API behaviours involved in that likely very limited use case where a summary element also contains nested links. For this, I'm happy to apologise up front, and if you're already thinking "TL;DR", you just might want to jump to the overview and upshot at the end. I won't be offended. The extensive detail is just me sharing what I've managed to grasp about how these things go together as part of an ever-continuing attempt to learn more about the ways screen readers, accessibility APIs, and browsers work. That, and somebody told me that blogging is making a comeback.

Current Browser Support

Neither Internet Explorer 9, Firefox 11, nor Safari 5 provide native support for details and summary. While Chrome has supported them for several versions now, its current version 17 provides no default keyboard access, nor does it pass any meaningful semantics to the accessibility API. However, recent WebKit nightly builds support the elements with proper keyboard access, as do recent Chrome Canary builds, but still neither provide any useful accessibility information. And Opera is working on it.

How They Should Work

The summary element should be natively keyboard focussable. Clicking or pressing the Enter or Space keys on the summary element should toggle the visibility of the details element's content. When the details element is expanded, it should have an open attribute present, and its content should be available via the system's accessibility API. Conversely, when the details element is collapsed, which is its default state, the open attribute should be absent, and the details' content should not be present in the accessibility tree. That is, it should not be available to assistive technologies.

According to the HTML to Platform Accessibility APIs Implementation Guide, the summary element should be mapped to a typical button role, or, where available, as in the Mac Accessibility API, a disclosure triangle role. There's more to say about this below.

Polyfill Required for Now

Where a browser doesn't manage this itself, the summary element should be made keyboard focussable with tabindex="0". Additionally, consistent with the proposed accessibility API mapping for the summary element, a WAI-ARIA role of button should be added to the summary element, along with an aria-expanded attribute that changes based on the state of the details element. The non-summary content of the details element should be hidden using display:none; when the element is collapsed.


<details>
   <summary role="button" aria-expanded="false" tabindex="0">
      Summary element content
   </summary>
   <p>Details element content</p>
</details>

The good news is that with a polyfill of your own design, or using something like Mathias Bynens' jQuery plugin for details/summary, things work pretty well right now in most browsers and screen readers. One current exception with Mathias' plugin is Chrome 17, which, because it natively supports details and summary, doesn't get the plugin's keyboard support applied. But since Chrome 17's keyboard support for summary is non-existent, this leaves Chrome keyboard users without the ability to expand or collapse the details. This isn't a problem using the plugin in tandem with Chrome Canary 19.

Here is an example a simple details/summary element in action:

summary element content

This is the content of this details element.

The bad news is that, if you include links in the content of the summary element, a few screen readers show rather problematic behaviour in some cases. Some of this has to do with the way certain screen readers manage keyboard interaction. Some of it has to do with the use of the ARIA role="button".

Note that when no screen reader is running, none of the browsers used in the tests below (namely Internet Explorer 9, Firefox 11, Safari 5, Chrome 17, and Opera 11) seem to have any difficulty providing access to both the summary and a nested link when using the Tab key (assuming keyboard access is supported either natively or through some polyfill).

Also note that the screen reader behaviour described below for the summary element goes for any other element you might use in a similar way. For example, if you're using a heading as the interactive element for showing and hiding other content, the same issues apply.

There's a Link in That summary!

The HTML5 specification for the button element, for instance, does not permit the nesting of other interactive content like links. This has always been the case, is expected given the typical use case of the button element, and so makes sense, I think. However, doing so, for better or worse, is permitted for the summary element, whose content model is phrasing content, which includes links.

I say "for better or worse" because, among other things, it could be easy enough, especially for sighted mouse users, to intend to expand or collapse the details element by clicking on the summary, but to accidentally click the nested link inside it instead. This would, of course, activate the nested link. However, it might be possible to mitigate this potentiality by clearly and visually distinguishing a link in the summary from the rest of the element, and providing a very obvious hover effect on the link to indicate the difference between clicking on it and clicking on the parent summary. Still, even then, I expect there remains some room for user confusion.

I've spoken to a few people who think it is a mistake to permit nested links, and that it is basically a bad design pattern. Personally, I have a feeling that it might be a potentially useful feature. My problem is that I'm unable to conjure a reasonable use case that argues well for this usefulness. Given the possible usability issue identified above, and the accessibility API and screen reader concerns discussed below, I don't know that I really have strong feelings about keeping nested links permitted in summary. It would, at least, be interesting to learn the reasoning behind permitting interactive content within the summary element.

Here's a details element with a summary containing a nested link surrounded by other inline text:

summary element with a link to google.com nested within it

This is the content of this details element.

The Effect of role="button"

In setting role="button" on the summary, we are effectively telling user agents to identify the summary as a button in the accessibility API. As such, we might reasonably expect that, as per the specification for the button element, any interactive content, such as links, nested in the summary would not be passed through as accessible objects to the accessibility API. In this case, of course, links nested in a summary would not be available to assistive technologies relying on the accessibility API. This is how it works at the moment with Safari and the Mac Accessibility API. Things aren't the same with Internet Explorer and Firefox, which leads to some especially interesting effects in JAWS and NVDA.

Safari 5 and VoiceOver

Safari 5 identifies our summary element with role="button" to the Mac Accessibility API as having an AXRole of AXButton, and any nested links are not passed to the accessibility tree. That is, as far as VoiceOver is concerned, there are no nested links, and the contents of the summary are flattened to basic text. The summary element content is read and announced as a "button". It is not possible to navigate to a nested link using the standard VoiceOver keyboard commands. You can set focus to a nested link via the TAB key, and you can follow the link, but the link text is not announced, and the link is not listed in VoiceOver Web Rotor's list of links.

Internet Explorer and Firefox

With Internet Explorer 9 and Firefox 11, on the other hand, even while a summary element with role="button" is identified to the accessibility APIs with a role of "pushButton", which is the same as a regular button element, links nested within the summary are passed through to the accessibility APIs, and thereby available to a screen reader should it wish or be able to use them. This last bit is important.

Just because the accessibility API provides certain information doesn't mean that an assistive technology can or will necessarily make use of it. For instance, both IE and FF pass the nested links to the accessibility tree as accessible objects, albeit somewhat differently. While IE identifies a nested link to the MSAA API as an MsaaAccessible link object, FF identifies it through the IA2 API as an IA2Accessible link object. For this reason, based on how they interact with the accessibility APIs, JAWS 13 and NVDA 2012.1 exhibit different behaviour in these two browsers where links nested in a summary element with role="button" are concerned.

Is role="button" Appropriate?

Unfortunately, accessibility APIs like MSAA and IA2 don't provide accessible roles fully suited to a summary element that contains nested links. Out of all the roles they offer, a role of button seems the most appropriate option. To the degree that a user agent deals with role="button" in a way that is consistent with the specification for the button element, i.e., disallowing the nesting of other interactive content, this presents a problem.

Steve Faulkner has called the situation "suboptimal", and proposed that the HTML5 specification be changed to disallow the inclusion of interactive elements. I rely on Steve's knowledge and expertise in these areas, and while I have no alternative solution to offer, I can't help wonder if, assuming that there is a potential usefulness to links in summary, that this proposal doesn't suggest a change in order to provide for what is really a current limitation of accessibility APIs.

Might there be another way to allow the summary element to contain other interactive elements while still providing reasonable access to assistive technologies? Perhaps something along the lines of the approach taken by IE and FF is the way to go, namely, identifying elements with role="button" to the accessibility API as having a button role, but nonetheless passing nested interactive content through to the accessibility APIs and thereby leaving it up to the assistive technology to determine how to handle it based on context?

As I noted above, I don't really have strong feelings either way, should the specification change to disallow nested interactive content. It certainly would address the problems with screen readers described below.

Nested Link Following Other Inline Text

We have two possible scenarios for links nested inside a summary element. In this first scenario to be examined, the nested link follows some other inline text, as is the case with our details/summary with nested link example from above.

In the second scenario, which we'll look at afterwards, the nested link is the first item in the summary element. This proves to be the most problematic scenario, at least with JAWS and NVDA.

The screen readers used to produce the results discussed below are:

  • JAWS 13.0.718
  • NVDA 2012.1
  • Window-Eyes 7.5.3
  • VoiceOver in Mac OS X Snow Leopard and Lion
  • ChromeVox 1.16.0
  • Orca 3.2.1 in Ubuntu 11.10

A Note on Browse versus Focus Mode

For what follows, it helps to understand the difference between the two main ways JAWS and NVDA (and some other screen readers) provide for interacting with web content. Browse Mode is the default navigation mode in which keyboard commands are intercepted by the screen reader enabling users to navigate a virtual representation of the page's content and structure. For example, in Browse Mode, the user can press the up or down arrow keys to move a virtual cursor up or down a line in the page content and have it read, or they can press certain keys and move to the next or previous link, or call up a list of all the links on the page.

Browse Mode is distinct from what is sometimes called Focus Mode, or often Forms Mode in JAWS, wherein keyboard commands are passed directly through to the browser, allowing users to do such things as input text into form fields.

JAWS and IE9

When in Browse Mode, JAWS and IE users navigating with the up or down arrow keys can move the virtual, or Browse Mode, cursor to a summary element. If the summary element contains nothing but text, all that text will be read and called a "button", but the expanded/collapsed state of the details element will not be identified, even though the aria-expanded attribute is present. If there is a link in the summary, however, JAWS will read it as a separate node, as it were.

If we take our details/summary with nested link example from above, upon arrowing down to the summary element, JAWS will read "summary element with a, button". Another down arrow keypress is required to move the Browse Mode cursor to the link and hear "link, link to google.com". A third down arrow keypress gets us to the remaining text in the summary, and we hear "nested within it, button". At this point it sounds like we've got two buttons and one link between them. And in fact, we do. If the Browse Mode cursor is on the link, pressing Enter or Space will indeed expand or collapse the details, but it will also activate the link. Consistent with this behaviour is the fact that the link nested in our summary element with role="button" is included in JAWS' links dialog listing all the links it finds on the page.

On the other hand, using the Tab key to move focus to the summary element, JAWS in IE will read its entire contents, so we get something like "summary element with a link to google.com nested within it, button". Activating it with Enter or Space simply expands or collapses the details element as we would hope. One can also use the Tab key to move focus to the nested link itself and then follow the link as usual, although this equally expands/collapses the details element prior to the nested link's URL being loaded.

JAWS and FF11

JAWS in FF11 similarly announces the summary as a "button", and doesn't identify the details element's expanded/collapsed state. Otherwise, it behaves a little differently. When moving the Browse Mode cursor to the summary element via the down arrow key, JAWS reads all of the element's content just as it does in IE9 using the Tab key, at which point pressing Enter or Space expands or collapses the details element without also activating the nested link. It's not possible with JAWS and FF in Browse Mode to use the up or down arrow keys to move the cursor to the nested link. Even using the left or right arrow keys to move the Browse Mode cursor onto the link text doesn't get JAWS to recognise the link.

Using the Tab key in Browse Mode, you can move focus to the summary and to the nested link, but even when focus is on the nested link, pressing Enter or Space does not activate the link, and only serves to expand or collapse the details element. The only way in FF to get JAWS to activate the nested link is to manually switch to Focus Mode (Insert + z), at which point, after setting focus to the nested link using the Tab key, one can fire and follow the link.

Considering this behaviour of JAWS in FF, compared with its behaviour in IE, it might come as no surprise that links nested in a summary element are not listed in JAWS' links list dialog. As far as JAWS in Browse Mode with FF is concerned, there are no links inside a summary element set with role="button".

NVDA, IE9 and FF11

NVDA behaves somewhat differently from JAWS, but more or less the same in both IE9 and FF11. The summary is announced as a "button", but NVDA respects the aria-expanded attribute, and so identifies the expanded/collapsed state of the details element. When navigating by the up or down arrow keys and setting the Browse Mode cursor to the summary element, NVDA treats it as a complete item and reads its entire contents: "summary element with a link to google.com, link, nested within it, button, collapsed".

One can use the right or left arrow keys as required to move the Browse Mode cursor to the link, at which point it gains focus and can be activated via the Enter or Space keys. The details element will at the same time be expanded or collapsed, but this hardly matters since the browser is already fetching the nested link's URL. Focus can also be variously set to the summary or the nested link using the Tab key, and the activation behaviour in both cases is the same. There's no need, as there is with JAWS in FF, to switch to Focus Mode.

Consistent with the above behaviour is that regardless of which browser is being used, NVDA's links list dialog includes any link nested within a summary attribute, even if the latter is set with role="button".

Nested Link as the summary's First Item

In this second scenario, the nested link is the first bit of content inside the summary element. Here's an example of that:

Link to google.com nested at the beginning of a summary element

This is the content of this details element.

JAWS and IE9

In IE9, as was noted above, when the summary element contains a link, JAWS parses its content as separate nodes in Browse Mode. If we use the down arrow to move the Browse Mode cursor to the summary element, the cursor moves to the first item in the summary. In this scenario, it lands on the nested link, and we hear, using the third details/summary example above, "Link, Link to google.com", with no indication that we are in a summary element as "button". Pressing Enter or Space obviously activates the link.

Another press of the down arrow and we hear "nested at the beginning of a summary element, button". At this point pressing Enter or Space will expand or collapse the details element without activating the link, but the relationship between what is read as the description of the "button" and the content that we are expanding or collapsing is hardly ideal.

If we use the Tab key to move focus to the summary element, the whole summary element's contents are read and called a "button". Pressing Enter or Space expands or collapses the details element, but it equally fires the nested link. The only way I've found to prevent this happening is to include some other inline text before the nested link. Even something like a non-breaking space character reference (&nbsp;) will do.

JAWS and FF11

Since we already know that in Browse Mode, and whether we use the up/down arrow or the Tab keys, JAWS doesn't recognise any nested links in the summary element with role="button", there is no real difference between scenarios one and two. Whether the link is nested at the beginning of the summary element or following some other inline text, the Browse Mode cursor and focus cannot be moved to the nested link. The only way to get to the link is to enter Focus Mode.

NVDA, IE9 and FF11

Just as with JAWS in IE, moving the Browse Mode cursor to the summary element and pressing Enter or Space to expand/collapse the details element ends up activating the nested link. And if we move focus to the summary using the Tab key, the same thing happens. James Teh, Director of NV Access Limited, makers of NVDA, kindly offered the following explanation:

This happens because when the [summary] gains focus, NVDA moves the Browse Mode cursor to the start of the [summary]. Unfortunately, the start of the [summary] is the link, so the Browse Mode cursor moves to the link. In Browse Mode, the Space and Enter keys always operate on the object under the Browse Mode cursor, not the focused object. (We need to do this because it's sometimes necessary to activate elements which aren't focusable; not every site is marked up as well as it should be.) Thus, pressing Enter activates the link.

James additionally noted that while he agrees this is a problem, a workable solution that won't also break a lot of other more common use cases is not easily had at this point. I have filed a bug report with NVDA (and another bug report for the same behaviour in JAWS).

Another pesky detail to mention here is that in IE9, even a nested link preceded by a non-breaking space character reference won't prevent the nested link from being followed. It takes actual text.

Also note that, while in Browse Mode, it is possible with NVDA in both IE9 and FF11 to move the cursor to the right of the nested link onto some non-link text, should it exist, and thereby expand/collapse the details element without activating the nested link. This is probably a little less intuitive than we should like, but it does provide the possibility of access. However, if the summary element contains nothing but a link, then we are totally out of luck, it would seem.

What About Other Screen Readers?

Window-Eyes 7.5.3

In both IE and FF, W-E 7.5.3 behaves the same. It announces the summary with role="button" as a "button", but doesn't identify its expanded/collapsed state. Links nested in the summary are not present in Browse Mode, nor are they to be found in the screen reader's links list dialog. Yet, apparently because of the role="button", W-E enters Focus Mode as soon as the summary element is activated, and then the links are accessible using the Tab key. But then reading the content using normal W-E's normal keyboard navigation commands requires manually turning Browse Mode back on.

With W-E, however, where focus is set to a summary element whose content begins with a nested link, activating the summary does not also fire the link.

ChromeVox 1.16.0

In Chrome 17.0.963.79, the summary element is not focussable. Links nested within it, however, can take focus and be followed. Interestingly, when setting focus to such a nested link, it is announced as a "button" and its expanded/collapsed state is noted. Nonetheless, it's not possible to expand or collapse the details content.

Orca 3.2.1 (Ubuntu 11.10)

Orca in FF11 provides full keyboard support to summary elements and any links nested within them. The summary is announced as "button", but its expanded/collapsed state is not identified. If a link is the first item nested within a summary, navigating by the up or down arrows will put the cursor to the link, and not the summary. In order to move focus to the summary parent, one can use the right arrow key to move to other non-link text if it exists. Otherwise, the only way is to use the Tab key.

Overview and Upshot

If you are using the HTML5 details and summary elements, and providing appropriate keyboard focus (i.e., tabindex="0") and WAI-ARIA support (i.e., role="button" and aria-expanded), users of most screen readers and browsers, at least more recent ones, will have little to no problem interacting with them. Mathias Bynens' jquery-details plugin works well.

Where role="button" and aria-expanded are applied to the summary element, JAWS 13, NVDA 2012.1, Window-Eyes 7.5.3, VoiceOver in Snow Leopard or Lion, and even Orca 3.2.1, all announce the summary element as a "button". Of these, only NVDA explicitly identifies the expanded/collapsed state of the element.

Chrome 17 is currently the only browser that supports details and summary. However, it does not provide keyboard support, which may leave keyboard-only Chrome users without access. However, recent nightly builds of WebKit and Chrome Canary support these elements with keyboard access.

Beware of Links in the summary

Things get tricky when we start to nest links within the summary element, which, no matter how you might feel about such a design pattern, is currently permitted according to its specification.

Links in a summary won't be clearly available to VoiceOver users with Safari. While such links are available to JAWS users in IE, they are not available to JAWS users with Firefox, nor to Window-Eyes users in either browser, unless one switches from Browse to Forms/Focus Mode, which likely won't be obvious to many. However, Window-Eyes does automatically enter Focus Mode as soon as the summary is activated, and then the links are accessible via the Tab key. And in NVDA, these nested links are available to users in both browsers.

It's also worth noting that links in the summary will change the way JAWS announces the summary's content in IE, reading it as separate nodes when accessed via the typical up or down arrow keys in Browse Mode. Using the Tab key gets past this, however.

When the summary Begins With a Nested Link

In JAWS with IE, and in NVDA with both IE and FF, setting focus directly to and activating a summary element whose first bit of content is a nested link will expand or collapse the details element, but at the same time cause that link to fire, which is likely to cause some serious disorientation. While NVDA users can play with the left or right arrow keys to move the Browse Mode cursor to any non-link text within the summary that might exist and then singularly expand/collapse the details element without also activating the nested link, this may not be intuitive. And if the summary contains nothing but a nested link, the user is pretty much out of luck: the nested link will always be fired when trying to expand or collapse the details.

The Upshot

Go ahead and use details and summary (with an appropriate polyfill). If you must have one or more links nested in the summary, arrange them so that they are not the first things within the summary element. And even if you manage this, you should recognise that:

  • these links still won't be in any way clearly identifiable to users of VoiceOver in Safari;
  • these links still won't be available to JAWS in FF or Window-Eyes in both FF and IE when these screen readers are in Browse Mode; and,
  • JAWS users with IE will have a less than ideal experience reading the summary's content.

Acknowledgements

Thanks to Steve Faulkner and Jamie Teh for their help and opinions, and for answering my technical questions about browsers, accessibility APIs, and screen readers.

2 Responses to Screen Readers and details/summary

  1. 1. Stomme poes:

    I assume it would be hella more work, but buttons are so limited by what they mean and do… I wonder if it makes more sense to create a whole new role for details/summaries if they are going to have interactive content inside them.
    When they have interactive content inside them, frankly, they are expected to act more like form select controls.
    Since they are not form controls, and since interactive content or a list of choices isn’t the sole possible content, the select role isn’t appropriate.
    We want the activation and status of a button but also some of the features of a select if needed. Might that be a new role?

  2. 2. Jason:

    @Stommepoes

    I’m not sure I agree with the analogy with select form controls, which have quite a distinct behaviour and don’t themselves permit other interactive content within them. The ARIA select role is itself an abstract role, so can’t be used. Of all the roles, button does seem the closest fit.
    The question for me is to do with what exactly user agents should do with elements set with a button role. Should the element acquire all characteristics associated with an actual button element, for instance flattening all nested interactive content to string text? I don’t get this from the ARIA spec for the button role. It seems to be how at least WebKit behaves, whereas FF and IE both pass nested links in an element with a button role to the a11y API, all the while enabling user-triggered actions on that element.
    I’m not sure what’s possible or feasible with the introduction of new roles in ARIA.next. Depending on a clarification of what user agents are expected to do with elements with the button (or other) role, it may be useful to consider new roles of some kind to fill those gaps that exist between what ARIA currently covers and what the APIs permit/expect.
    Thanks for your comment!

Comments are now closed.