Introduction to ARIA
This topic introduces Accessible Rich Internet Applications (ARIA) markup. You learn how widgets, a term ARIA uses to describe HTML controls, are used to make accessible custom UI controls such as buttons and menus. You also learn how to use ARIA's landmark roles for navigation and live regions for dynamic content areas.
This topic contains the following sections:
- A New Approach to an Old Problem
- What is ARIA?
- Navigation Using ARIA
- Live Regions
- Putting It Together
- Related topics
In Introduction to Web Accessibility and in Semantic HTML, you saw how to write HTML by using the proper semantic elements and attributes in order to expose element semantics to assistive technology. However, that is only a part of the problem.
These semantic techniques do not provide solutions for the now common dynamic websites. Web content that is created or updated after the page is rendered can be an issue for accessibility. The World Wide Web Consortium (W3C)'s 1999 standard, Web Content Accessibility Guidelines (WCAG) 1.0 addressed the issue of static content, and the 2008 revision, WCAG 2.0, includes guidelines and techniques that address dynamic content.
Many common issues with dynamic content can be addressed by good coding practice, and the WCAG 2.0 documentation includes many techniques and best practices to help developers create more accessible dynamic web applications. Even when coded properly, however, dynamic content is not necessarily accessible.
Because HTML has native support for only a few user interface controls (links and form elements), developers often create their own controls by using a combination of HTML elements and script. The script changes the purpose (role) and state (properties) of the HTML elements that are used to build the controls, but these changes are not exposed to assistive technology.
To overcome this problem, a new solution evolved, ARIA. ARIA extends HTML by using additional attributes that are designed to convey custom semantics. These attributes are used by browsers to pass along the controls' state and role to the accessibility API. The most common problems that ARIA addresses are:
- Keyboard interaction (tabindex)
- Exposing the purpose and state of a control (role and properties)
- Exposing the purpose of content (landmark roles)
- Exposing changes in content (live regions)
ARIA emerged as a way to address the accessibility problem of using a markup language intended for documents, HTML, to build UIs. HTML includes many features to deal with documents, such as paragraphs, headings, lists, tables, and so on, but only basic UI elements, such as forms and links, that are mapped to accessibility APIs by browsers. Browsers cannot take advantage of additional functionality when the basic elements are extended. For example, adding a click event to a span or image does not map the image as a button.
The solution was to create a set of attributes that developers can use to extend HTML by using UI semantics. The ARIA term for a group of HTML elements that has custom functionality and uses ARIA attributes to map these functions to accessibility APIs, is widget. It is important to note that ARIA is most appropriate for complex or unusual UI elements; many common UI elements can and should be built by using native HTML.
Another case where ARIA can be quite useful is in adding accessibility features to existing websites and web applications that are built with HTML. ARIA markup can be added without changing the behavior for mainstream users, greatly reducing the cost of modifying and testing the website or application.
ARIA takes the existing tabindex property from HTML and extends its use. In HTML, tabindex could be set only for a few elements and could have only positive values. ARIA extends this to allow any visible element to be assigned a tabindex. It also allows for the value -1 to be set, which takes the element out of the tab order altogether while still allowing programmatic focus.
Together, this allows you to create better navigation experiences for the user. Consider, for example, the case of a complex drop menu, where each top-level menu item contains dozens of items. Tabbing through every child menu item is tedious and time-consuming for keyboard users.
You can avoid this by setting the tabindex of these children to -1, making the tab order include only the menu titles. You can also use arrow keys or other common navigation paradigms to work with the child menu items, using the aria-expanded or aria-haspopup properties, together with the ARIA menu role to communicate this functionality to assistive technology.
Consider an image used to invoke some action.
<img src="mybutton.gif" onclick="doSomething();">
This approach has many accessibility problems. There is no keyboard focus, there is no keyboard interaction, the Microsoft Active Accessibility role is graphic, and the name is null, which many screen readers read as the fully qualified URL. A keyboard user cannot focus on or invoke this control, and assistive technology users have no indication of what the control does. You can correct for these issues by using ARIA.
<img tabindex=0 onkeypress="doSomething();" role="button" alt="Do Something" src="mybutton.gif" onclick="doSomething();"/>
You can address the keyboard issues by adding the tabindex attribute and onkeypress event handler. Now the button is able to be invoked, but to assistive technology it still seems to be merely an image with no name. The role attribute is the answer here.
It assigns an ARIA role to the control, which gets mapped to the Microsoft Active Accessibility role and Microsoft UI Automation control type with the alt text as its name or value. Now assistive technology users will be presented with a button named "Do Something" and they will be able to invoke or "press" the button.
Use native HTML semantics where possible, for example, button in this case. So ARIA are not appropriate in a case as simple as this. The following examples are more complex, but built on this simple concept to show how you to use ARIA to document complex user interfaces that are not natively supported in HTML.
Add complex UI functions on top of valid HTML only. This technique is called progressive enhancement. Progressively enhanced content provides a better assistive technology user experience with ARIA, and still works for older browsers.
Elements can be extended with the role attribute to document the purpose of the control. This is done at the top level of the controls hierarchy, or widget, to document the control itself, and at the child level to document the purpose of sub-elements.
<ul role="tree"> <li><a role="treeitem" aria-expanded="false" ><img src=" p.png" alt="+" />Documents</a> <ul role="group"> <li role="presentation"><a role="treeitem" href="File1.htm">File 1</a></li> <li role="presentation"><a role="treeitem" href="File2.htm">File 2</a></li> <li role="presentation"><a role="treeitem" href="File3.htm">File 3</a></li> </ul> </li> </ul>
This example demonstrates a simple expandable tree view (script omitted for brevity) that exposes its role of "tree", and its children as "treeitem", "group", and "presentation". The role values can represent both a mapping to control types, for API, and the purpose or intent of the element such as grouping and presenting other content. Role is used quite flexibly in ARIA, as you will see with landmarks later in this topic.
Generally, the top-level element should be mapped to a common control type for complex controls such as tree, slider, or dialog. Sub-elements can be control types themselves, such as tabbed dialogs, sub-types such as menuitem, or can have only a general purpose such as grouping. ARIA has attempted to provide a comprehensive list of possible roles to choose from. The full list of role definitions can be found at the W3C.
For a working sample, see the Tree Control Sample.
By using the ARIA role, you have a means of presenting what a control is, or can do, but no way of presenting the current state of what it is doing. ARIA uses a set of extended attributes to document the state and properties of elements within the control. Some properties can be set for any element and some are intended for elements of specific types and their children. So, for example, the aria-expanded property is expected for treeitems, as seen in the previous example, but would make little sense on a button.
States and properties can serve two purposes. They convey to the browser what the control's state is, allowing the browser to send this to the accessibility API. And scripts can also make use of the ARIA role, states, and properties rather than custom attributes or other mechanisms, to manage the state and behavior of the custom control.
For example, instead of hand-coding the popup behavior for a submenu directly, you can use code that finds widgets with menu roles, looks for aria-haspopup on menuitem children, and dynamically adds the event handlers to the appropriate aria-labelledby child.
ARIA properties offer features not supported in HTML. By using these properties, you can add semantic information into the markup, which documents the purpose of the control. The check box control is a good example. The ARIA check box is a tri-state check box, supporting checked, unchecked, and mixed, whereas the HTML check box is two-state, supporting only checked and unchecked.
If the native functionality is sufficient, it is much less work and better practice to use it. But when you need functionality beyond HTML's native controls, ARIA allows you to create it and convey the "what, how, and why" of it to assistive technology.
Sometimes you simply add look and feel, not functionality. If you want a prettier check box, or a windowless check box that works better with other HTML controls, you must construct your own. By using ARIA, you do not need to exclude users with disabilities to achieve the look and feel you want for your sites.
For more information about ARIA roles, see Mapping ARIA Roles, States, and Properties to UI Automation. A full list of ARIA states and properties can also be found at the W3C.
In addition to roles that convey the control type of a widget or the type of behavior for an element, ARIA also has "landmark" roles that are used to convey the type or purpose of content and are intended to improve the experience of navigating content. They address the problem that assistive technology faces in navigating a site, so that instead of listening to or tabbing through every element in the page's navigation bars, advertising, and so on, assistive technology users can navigate directly to the section they want.
Before ARIA, this was often handled with skip links, a link at the top of the page that jumped to the main content or other frequently used parts of the page. Skip links are less than ideal, because they can interfere with the visual layout of the page and can be confusing for sighted users.
By providing a common set of semantics for specifying page and site navigation, ARIA allow authors and developers to document the different types of content on the page, so that assistive technology can provide a way for users to navigate quickly to that content. The same role attribute is used as before; simply use a different set of values.
Rather than specify a div to be a control type, such as a button, specify its content type, such as "main" or "search". Specifying a content type exposes to assistive technology that this content is a landmark, meaning a logical chunk of the page's content, and what type of content it is. Landmarks are used by assistive technology to create enhanced navigation experiences. For example, a screen reader can provide a keyboard shortcut to cycle through the landmarks on a page, reading out the role of each.
The landmark roles found on the W3C website are:
Applications tend not to be static. An email application that doesn't update when mail is received is not very useful. But assistive technology cannot process a new chunk of HTML that is added to the Document Object Model (DOM). A sighted user might see a new row added to their Inbox and see that it is a new message, but without contextual and semantic attributes, assistive technology cannot interpret this. ARIA calls these updatable content areas live regions.
Live regions are elements that are expected to get updates at run time. The elements are typically div, table, and so on, that naturally hold content. For the e-mail application mentioned previously, you might have a div that contains child div elements in a microformat for mail headers. By setting the parent div element's role to "log," assistive technology knows to "watch" for new children and voice them to the user.
An element may be set as an ARIA live region in two ways. An ARIA role may be set on the element that is a live region role: "alert", "status", "timer", "marquee", or "log". This not only indicates to assistive technology that this element will be updating, but also conveys the semantic type of the region. If the element is not one of the explicit live region types, the aria-live attribute may be used. For a complete list of roles, see the W3C website.
In the first case, the verbosity of the live region is inferred from the role, and in the second case it will be the value of the aria-live attribute: "assertive", "polite", or "off". The aria-live attribute may be added to any element.
When using live regions, the first step is to identify what parts of the page will be dynamically updated. Of those, identify which ones are native ARIA live region types and the priority of each area's updates.
The trigger and scope of the updates must be specified as
well. Decide how much context is
needed. If you want the whole live
region read, use
decide what types of changes to announce:
text" (space-separated list, default is additions removals). The W3C provides examples of
using live regions.
Let's go beyond a simple button to a common HTML use case: the dynamic menu. Historically, these have been constructed using ul or div elements. Accessibility advocates have argued for using the ul element because many assistive technologies assume these to be menus, creating alternate navigation modes for the user. With ARIA, you can safely use either element because the ARIA attributes document the semantics more concretely than the tags can.
The typical fly-out menu looks similar to the following example.
<div id="menuBarMain"> <div id="Menu1"><a href="#">one</a></div> <div id="Menu1Popup"> <div><a href="#">a</a></div> <div><a href="#">b</a></div> <div><a href="#">c</a></div> </div> <div id="Menu2"><a href="#">two</a></div> <div id="Menu2Popup"> <div><a href="#">a</a></div> <div><a href="#">b</a></div> </div> </div>
The div elements are positioned using Cascading Style Sheets (CSS), and script hides and shows child menus in response to keyboard and mouse activity. The problem is that this legacy approach doesn't push information into the accessibility API where it is available to everyone.
This is the crux of what ARIA provides to authors. By managing the ARIA properties, you can directly affect the values presented by using APIs. The essential tasks when building ARIA widgets are then to document the roles, specify the initial properties, and marshal state changes for these properties into the Accessibility API by dynamically managing the ARIA properties at runtime.
The following examples include the ARIA properties that you use to create a menu.
The menubar role of the outer container tells the assistive technology that you intend the child elements to be a top-level menu, or list of menus.
The top-level item gets a menuitem role and aria-haspopup indicates that there is a pop-up menu controlled by this menu item.
The pop-up menu itself gets a menu role. Set it as "labelledby" the
Menu1 div, and set its initial state to hidden. Be aware that you no longer need to track it by ID because you can use ARIA methods to parse the menu tree.
<div role="menuitem"><a href="#">a</a></div> <div role="menuitem"><a href="#">b</a></div> <div role="menuitem"><a href="#">c</a></div> </div> <div role="menuitem" aria-haspopup="true" id="Menu2"><a href="#">two</a></div> <div role="menu" aria-labelledby="Menu2" aria-hidden="true"> <div role="menuitem"><a href="#">a</a></div> <div role="menuitem"><a href="#">b</a></div> </div> </div>
<script> // toggle code omitted for brevity menu.setAttribute("aria-hidden", true); </script>
Here, you merely keep the aria-hidden property in sync with the menu's state.
This is only a very brief illustration of how and where ARIA attributes would be added. Issues about how to preserve the widgets' state, or even invoke the toggle method, are beyond the scope of an introduction. This will be discussed fully in the article on creating a menu widget in ARIA.
The important thing to take away from this example is that ARIA allows more than merely documenting the role of a custom control by using the role attribute; it allows you to expose the properties and states of the controls to users with the accessibility APIs. In other words, it allows you to work with these APIs from script by managing the various ARIA attributes.
For a working sample, see the Menu Bar Sample.