Not All ARIA Widgets Deserve role="application"

There are currently some great examples of WAI-ARIA-enabled widgets out there making the rounds. In particular, there's Hans Hillen's JQuery Widget Samples and the collection from the OpenAjax Alliance.

These are nothing short of very useful. After all, ARIA is yet to be a full W3C recommendation (or standard, if you prefer), and we are all, or at least I am, still learning to write widgets with ARIA as best we can while assistive technologies continue to improve their support for it.

At the same time, I've noticed a few things about how some of these examples use the ARIA role="application" attribute and value, and how certain screen readers deal with it, that I think are worth exploring.

In Which I Go on Yet Again About Tabs

I'm not sure what it is with me and tabbed interfaces. Perhaps, because of research I've done in the past, they are just something I feel comfortable and familiar with. In any case, when faced with a collection of sample ARIA widgets, I tend to gravitate to the tabbed interface examples first. I like to check out how they've been implemented and how they work with screen readers, usually JAWS and NVDA since these have the best support for ARIA right now.

Tabbed interfaces remain a common way to present web content, whether it's a series of form controls, images, or blocks of text; whether they are displayed horizontally or vertically; and whether they are presented as an accordion widget, or something like a sliding carousel or slideshow.

Are Tabbed Interfaces Applications?

This is the wrong question to ask. Instead, we should ask, "Is the content presented through the tabbed interface an application?" For instance, in the OpenAJax Alliance's tabs example, the content in the tab panels comprises a series of form controls for ordering a pizza, allowing you to specify the type of crust, toppings, and mode of delivery you desire. Except for the heading that appears in each panel, the content is nothing but interactive controls requiring input from the user. This is pretty obviously an application.

On the other hand, the tabs example on the JQuery Widget Samples page presents three tab panels that provide straightforward text content (including some links) describing dogs, cats, and sheep. Except for the minimal interactivity offered through the links contained in the text, the content is solely for reading. While one might consider the simple presence of tab controls to make this an application, I would suggest that because of what the tab panels contain, what we have here is not an application, but simply a particular presentation of regular text content that makes use of certain application-like, navigational controls. The user is not being asked to input any information to be processed, and the use of the tabbed interface is essentially presentational.

Why Does This Matter?

If it weren't for NVDA, I doubt that I would have as much to say about this. Allow me to explain; but first, a quick recap of virtual buffers and such.

Screen readers and Forms, or Focus, or Application Mode

When working with a web page, screen readers like JAWS and NVDA mostly read from a virtual buffer, what is effectively a snapshot of the DOM. Users can move through the virtual buffer of the page using special keyboard commands specific to the software. When in this virtual buffer mode, keyboard commands are intercepted by the screen reader and not passed through to the browser.

Since application widgets in the browser need to allow direct keyboard input from the user, screen readers also have a forms or focus mode. In the particular context of application widgets, we might also call it application mode. In this mode, keyboard commands are passed through to the browser and not intercepted by the screen reader. This allows the user to do things like type text into a form field, or change the currently active panel in a tabbed interface by using the arrow keys.

Tab Controls Initiate Application Mode by Default

When focus is set to a tab control, that is, an element that has an ARIA role of tab, both JAWS and NVDA automatically enter application mode, since the intended interaction for tab controls is to use the arrow keys to navigate among them. Once in application mode, moving focus, for example, by using the Tab key, from a tab control to a focussable element that does not require forms or focus mode, such as a link or checkbox, causes both screen readers to automatically exit focus mode. This occurs even if the focussable element is within the tab's associated content panel.

Additionally, if focus is currently set to a tab control, both JAWS and NVDA users can just as easily exit application mode manually with simple keyboard commands, and move on to navigating and reading the tab panel's content as they wish using the virtual buffer. So far, so good.

Adding role="application"

In the OpenAjax example, an ARIA attribute-value pair of role="application" is set on a div containing the tabbed interface elements, that is, the tab list, the tabs themselves, and their associated tab panels.

In the case of the JQuery Widget Samples page, all of the widget examples are collectively presented through a tabbed interface. A container div with role="application" wraps this overall collection of tab panels. Because the specific tabs widget example is contained in one these tab panels, it inherits the effects of role="application" from the container div. Additionally, the body element on the page is also set with role="application".

Using role="application" tells supporting assistive technologies to change their mode of behaviour. Instead of intercepting keyboard commands to allow interaction with the virtual buffer, they pass all keyboard input through to the browser as if dealing with an application. This goes for all of the content wrapped in a container with this role, whether it's made of up explicit form controls or just simple text.

JAWS' Behaviour

Freedom Scientific has provided a Word document on how JAWS deals with ARIA, which has been kindly reproduced in HTML by the Paciello Group. In it one finds the following.

In HTML, when the ARIA role attribute on the BODY tag is set to “application”, JAWS will treat a Web page as though it were a traditional stand-alone application. This means that the virtual buffer JAWS typically uses to display Web pages will be turned off, and users will navigate using TAB and other such keystrokes which are normally provided in stand-alone apps to facilitate keyboard access…. And unlike forms mode, users cannot use the ESC key or the PC Cursor key to leave application mode when the role of “application” is placed on the “body” tag.

This is perhaps a little misleading, as it suggests, I think, that a JAWS user simply cannot exit application mode when role="application" is applied to the body tag. However, one can always press Insert+Z to toggle the virtual cursor, and thereby effectively leave application mode and start interacting with the widget's content through the virtual buffer and standard JAWS reading commands. This, I think, is very handy, especially where a widget contains content that is meant to be read, but it is quite different from the approach that NVDA takes, as we'll note shortly.

When focus is within an element with role="application" that is a descendent of the body element, JAWS users can still use Numpad+ to exit application or forms mode, and easily start reading the page's content. At the same time, in this scenario, JAWS will not automatically exit forms mode when focus is set to elements such as links or checkboxes as it normally would outside the context of role="application".

NVDA's Behaviour

For NVDA, when dealing with objects set with role="application", the virtual buffer just doesn't exist. Pressing Insert+Space to toggle virtual buffer or browse mode does nothing. Content inside an element with a role of application is just not rendered into a virtual buffer, and will never be available through NVDA's normal reading commands. Where such a widget's content is all application controls, as is the case with the OpenAjax tabs example, this is not a problem, as all of the content is natively focussable.

In the JQuery tabs example, on the other hand, where the tab panel content is a series of texts about dogs, cats, and sheep, this does present a problem. The only way for an NVDA user to read the tab panels' content is to use NVDA's object navigation commands, which allow the user to move from node to node through the DOM, reading each one as it goes. While this is an essential mode of navigation to provide, using it in this instance can make reading the text a rather disjointed affair.

For example, the text from the first sentence in the "Dogs" tab panel is The dog (Canis lupus familiaris,[1] is a domesticated form of the wolf, a member of the Canidae family of the order Carnivora. This one sentence includes a good number of DOM nodes, including a, b, i, span, and sup elements. Reading it by object navigation involves pressing the same key combination, Ins+Numpad6, a total of 14 times to move through ever node in the sentence: hardly a pleasant way to navigate or read text!

Whether pleasant or not, this behaviour is at least consistent with the way that James Teh, one of NVDA's lead developers, considers the question of role="application": ...an application should *never* be rendered into a virtual buffer. It's not just a question of browse and focus modes; an application is not supposed to engage the virtual buffer at all.

So What's the Gist?

Personally, I don't fully understand why NVDA so strictly keeps application content from being rendered in a virtual buffer, but I also don't understand much of the inner workings and programming of screen readers. While I certainly appreciate the benefit in JAWS allowing users to enter, albeit through more limited means, a virtual buffer even within an application, I'm happy to trust that NVDA's developers know what they are doing.

Certainly, in accordance with NVDA's behaviour, the result for developers is pretty obvious: Only use role="application" for true applications comprising form and other interface elements that demand user input. Or, as James puts it, role=application should not be used if the content could in any way be considered a 'document' which should be browsed.

But I think this holds even where JAWS' behaviour is concerned. It is clear from its more restricted approach to forms mode when role="application" is applied to the body or a descendent element that the same idea is at play, namely that applications are for interacting with directly through browser-level keyboard commands, and not through a virtual buffer.

Revisiting Our Examples

The OpenAjax Alliance Tabs Widget

As was noted at the beginning, the OpenAjax Alliance's tabs example can easily be considered an application. The content is really nothing but natively focussable form controls through which a user is meant to place their pizza order. With the slight exception of the heading text in each tab panel, there is no content that is meant to be browsed or read like a document. So role="application" in this instance is perfectly fine.

As far as the heading text is concerned, it is not natively focussable, and will not be read by either JAWS or NVDA in application mode. Still, it is useful text to have since it adds context to the purpose of the list of controls in each panel. To make this text more readily available to screen reader users, it might be useful to give the heading an id and reference it through an aria-labelledby attribute on the ul element wrapping the form controls. This would cause the screen reader, upon focus being set to the first item in the list of controls, to identify the list using the heading text. If we did this for the "Carnivore" tab panel, for example, NVDA would say "Carnivore property page, Select Carnivore Options, list, Pepperoni checkbox, not checked."

The JQuery Tabs Widget

For the JQuery tabs widget example, the tab panels' content is text about dogs, cats, and sheep that is meant to be browsed as a document: a screen reader user should be able to navigate and read the text through a virtual buffer's normal reading commands. As such, it should probably not use role="application". The tab controls themselves already initiate forms or application mode when receiving focus, so programmatically identifying the whole thing as an application is unnecessary in this regard. Doing so, however, does significantly reduce the ability of at least NVDA users, and to some degree also JAWS users, from accessing the panels' content.

I should clarify again that the individual JQuery tabs widget example is not explicitly wrapped in its own element set with role="application". It exists in its own tab panel as part of a larger set of tab panels wrapped by a div set with a role of application. This amounts to the same thing, though, as far as screen reader behaviour goes, since the effects of role="application" on the container div are passed down to the element's children.

I would suggest that role="application" should not be added to the div wrapping the overall set of tab panels. In some cases, the sample widgets, notably the accordion, tabs, tooltip, and panel widgets, contain text content that should be browsable. Also, each sample widget appears in its own tab panel, and is accompanied by additional text identifying what accessibility changes have been made to the widget since its last incarnation. This additional text, and the text within those particular sample widgets just mentioned, will be difficult to access and read for NVDA and JAWS users.

For the same reasons, I would also say that role="application" should not be set on the page's body element either. Instead, role="application" should probably only be applied to those specific widgets, e.g., the slider, menubar, checkbox, and tree, that are expressly application controls and that don't include any typically browsable or document-like content.

Conclusions

I've concentrated on two examples of tabbed interfaces that use role="application". However, the concerns that have been raised extend equally, I think, to all ARIA widgets where one might be apt to use role="application".

When building an ARIA widget, consider the widget's content and the type of interaction that users of screen readers and other assistive technologies will require. If the widget contains text for browsing, as opposed to text that is directly associated with a specific control or that labels a group of controls, just forego using role="application".

Only if the widget contains mainly application controls is role="application" likely appropriate. And if it also contains some text that is meant to label or further describe those controls, consider using the aria-labelledby and aria-describedby attributes to associate that text as applicable.

Acknowledgements

I really have to thank Hans Hillen and the OpenAjax Alliance for creating and sharing their sample ARIA widgets. Despite my raising some issues with their implementations, without these examples there would be much less to work with as we try to figure all this stuff out. I'm grateful for the learning opportunity. I'm also thankful to James Teh for answering some of my questions about how NVDA works and interprets role="application".

12 Responses to Not All ARIA Widgets Deserve role="application"

  1. 1. Artur Ortega:

    I would rephrase your title to:

    Avoid role=”application” as much as possible in ARIA Widgets

    I’m blind and using a screen reader (JAWS & NVDA). I personally don’t like if my main way of interaction changes dramatically. This is the case with role=”application”.

    I know that there are some rare cases where we can’t avoid the application role but I have the feeling that sighted users aren’t aware of the profound difference of interaction blind users are facing.

    Blind windows users already have to deal with at least two traditional interaction modes: browsing and forms mode – and in some cases object mode.

    The application mode adds an additional complexity wich can in the most of the cases be avoided.

    The main reason for the decision to use an application role at the moment is the lack of having access with javascript to the key-strokes by a screen reader user and NOT because it’s fundamentally an application widget.

    That’s why it’s so important to explain to developers that there are already ways to gain access to key-strokes in javascript when using a screen reader – without using the application role.

    Your section about the forms mode is the key for avoiding application roles.
    We don’t have only forms mode in input elements, we have them on tab and menu ARIA-roles, too, at least in JAWS.

    In the moment a blind user interacs with a ARIA tab or menu they are using a familar interaction concept – the forms mode – no new interaction occurs.

    In the forms mode the developer is able to gain access to any key-stroke and can code as there wouldn’t be any screen reader interception.
    This concept is already widely used for regular input elements – like in the Yahoo! currency converter for auto-suggestion of currencies.

    Every time I feel caught in the application mode I ask myself: “Was it really necessary to use the application role?”

  2. 2. Jason:

    Thanks very much for your comments, Artur.

    I have wondered both how screen reader users feel about being forced into application mode, as well as how familiar most non-power screen reader users are with the concept, since it is still rather new. I’m not sure how best to phrase the questions to get at this information, but think it would be interesting to try and learn more about it, perhaps through something like WebAIM’s screen reader survey.

    The main reason for the decision to use an application role at the moment is the lack of having access with javascript to the key-strokes by a screen reader user and NOT because it’s fundamentally an application widget.

    Thanks for noting this. I wonder if another way to say this is that what fundamentally makes an application widget is the requirement to have access through JavaScript to user keystrokes?

    What’s important is that, as you note, for some of the main widget roles, screen readers like JAWS and NVDA that support ARIA already provide this access to keystrokes by automatically entering forms mode. This certainly ends up being more useful to screen reader users since they will be more familiar with it, and they’ll always have access to the virtual buffer should they need or want it. In addition to tab and menu roles, the tree role also appears to initiate forms mode. I’m thinking that it might be nice to compile a list of what roles in particular are associated with this functionality and for which screen readers.

    The YUI 3 TabView widget, for example, does not use role="application" and works really well. In fact, it allows some slightly different but what would seem to be very beneficial interaction for screen readers that I find quite interesting, and which I hope to address in an upcoming blog post.

  3. 3. James Teh:

    Very nice, thorough article!

    It’s worth noting that this isn’t so much specific to the “virtual buffer” approach, but more generally relates to browser caret navigation. The problem is that whenever caret navigation is in effect, the cursor (and other) keys are overridden, so the only way to allow full interaction within an application is to disable caret navigation altogether. I’m guessing this is probably an issue in Orca as well (which uses caret navigation but not a virtual buffer), though I’ve never tested, so could be wrong. The only real solution to this is to move away from flat caret navigation altogether. A possible alternative is to use object navigation for everything, which is the approach taken with VoiceOver and Safari on the Mac. While I posted this for other reasons at the time, I discussed this a bit in this blog post:
    http://blog.jantrid.net/2009/10/object-navigation-why-is-it-okay-for.html

    When you say “I don’t fully understand why NVDA so strictly keeps application content from being rendered in a virtual buffer,” I assume you mean you want to be able to toggle the virtual buffer on and off, rather than just always using a buffer, which would totally defeat the point of the application role. I guess we could consider implementing a toggle, though aside from contradicting the intent of the application role (which shouldn’t be present at all if it isn’t truly application content), it adds more complexity to an already fairly complex area; we’d need yet another mode keystroke, etc. Also, NVDA basically treats application content in a web document exactly like it treats normal desktop applications, where there is no such toggle. Still, it might be something we need to consider as a work around if the incorrect use of the application role continues into the future.

  4. 4. Jason:

    Thanks, James, and thanks for clarifying the virtual buffer versus caret navigation versus object navigation issue. I had read your blog post on object navigation about a year ago, but reading it again just now it makes a lot more sense to me.

    Concerning object navigation, it is obviously a crucial form of interaction to provide. It’s interesting to note that in VoiceOver’s object navigation, one can read the text in the “Dogs” panel from the JQuery Widget Samples page by discrete node, but also by sentence and by paragraph. One can also read the entire contents of the VoiceOver cursor by pressing Ctrl+Option+A, which, if focus is at the top of the tab panel, effectively causes VoiceOver to read all the text in the panel, also announcing links as they occur.

    This doesn’t seem possible with NVDA, or maybe I just can’t figure it out. I would have expected the “say all objects” command, NVDA+NumpadPlus, to do this, but it doesn’t seem to work at all in application mode. Incidentally, I’ve been using versions 2011.1beta2 and 2010.2. I do note, however, that in your blog post you say that NVDA’s object navigation needs to be cleaned up a bit (removing extraneous objects, etc.), so maybe this has something to do with that.

    Regarding my lack of understanding around NVDA’s approach, it is really just a matter me being ignorant of the complexities in how the software actually works. That said, and as I mention in the article, there does seem to be some benefit to users to be able to toggle out of application mode, at the very least in those cases where role="application" might be wrongly applied to content that is to be browsed. However, asking if NVDA should decide to go this way seems to involve that question, already well-covered in the HTML5 discussions, of whether or not we should be writing technologies and specifications in order to support poor developer practices, which really isn’t the most fun discussion to have. As such, I’m happy enough to leave that one to you and your team :)

  5. 5. Mike Becvar:

    Are there other implications of using or not using role=”application”? We are just starting to get into adding ARIA to the materials that we are developing. Since this is still a developing set of standards, there aren’t too many working examples available. I should note that currently, IE7 is our target platform, but want to develop something that is cross-browser. In some testing, I noticed that in IE7, Jaws would not read the content of an alert (role=”alert”) unless it was within an application (role=”application”). Firefox, on the other hand, did read the alert just fine.

    Isn’t it better to follow the best practice examples and hope the browsers/screen readers eventually all work the same way? I would hate to leave off the role=”application” and find out a year from now that I need to go back and add it into all of my pages.

  6. 6. Jason:

    Mike,

    As you mention, the standard is still being developed, so there may well exist other implications of using or not using role="application that crop up in the future. And with the current support for ARIA in browsers and assistive technologies, what constitutes best practice from the point of view of the specification, such as it is, may or may not result in an ideal experience for your current users depending on the technology they are using.

    That said, I think that the concepts behind role="application", in particular the treatment of keyboard input, is pretty set. This is also where the current major implications of the role’s use are evident, as I tried to detail: Using role="application" to wrap content that is for reading or browsing is likely going to cause headaches for screen reader users.

    Regarding the point you raised about role="alert" and JAWS in IE7, I was intrigued, so I whipped up an ARIA alerts test case. From my tests, I didn’t recognise any difference in the behaviour of JAWS 10 or 11 when an alert was contained in an ancestor element with role="application". What version of JAWS were you using? Do you have an example you can point to?

    My test case does, however, indicate that doubling up on role="alert" with aria-live="assertive" does make a world of difference for JAWS 10 in IE7 and IE8, and doing so shouldn’t be a problem since ARIA alerts are by specification already assertive live regions. In any case, maybe the results from these tests will be helpful to you.

    Thanks for your comment.

  7. 7. Mike Becvar:

    Sorry, I don’t seem to have the actual page I was using. I had created a page with a series of divs, each a paragraph of text that indicated what role had been set. I was using all of roles that Jaws is supposed to support, navigation, application, article, banner, etc. I was testing the page with Jaws 12 along with IE 7 and Firefox 3.5. When I added a button to populate text in an alert it was not reading the content of the alert. I saw that Jaws/IE 7 combination worked on the alert example from the Illiniois Center for Information Technology and Web Accessibility and it started working when I put the alert in the application. I don’t know if the issue was the page being cached on the server, my lack of experience with Jaws, or some other mistake I had made.

  8. 8. Steve Buell:

    Jason,
    Another great article, thanks!
    I was wondering about one thing though: in the The OpenAjax Alliance Tabs Widget sample shouldn’t the heading text in each tab panel actually be a “legend” for a “fieldset”?
    This would enable them to grouped together and read as they should be.

  9. 9. Steve Buell:

    Hi Jason,

    I modified a local copy of the OpenAjax Alliance Tabs Widget code to change the h3′s legends inside a fieldset and applied CSS to remove the border and style the legend text the same as the tab list.

    It seems to work just fine and there is only a minor visual difference.
    It should work better with screen readers now that the proper semantic code is applied. I’ll be testing it when I get access to my tools at home (work computers are “secured”).

  10. 10. Jason:

    Hi Steve,

    Thanks, and yes, you are totally right: fieldset and legend should be applied as you describe to each set of controls, especially as they are radio and checkbox inputs. The change in visual styling can always be fixed with CSS.

    Thanks for pointing this out. It is the right approach, and much better than applying the aria-labelledby modification I suggested: No need to bother with extra ARIA attributes when the appropriate plain old semantic markup will effectively do the same job, and is more compatible across all browsers and AT.

  11. 11. Steve Buell:

    Thanks Jason,
    I wasn’t critiquing your suggestion as much as I was commenting on the sample from the OpenAjax Alliance Tabs Widget code.

    WAI ARIA recommends using native semantics over the application of ARIA wherever possible to improve compatability.

    The work you are doing has tremendous value and I look forward to all of the tests you post.
    Thanks

  12. 12. Jason:

    @Steve,

    I didn’t take it as a criticism, so no worries there :) But it is, without a doubt, the right approach, so I’m happy you offered that comment. Cheers.

Comments are now closed.