[contents]
Copyright © 2009 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
This document describes how user agents should respond to roles, states, and properties provided in Web content via WAI-ARIA [ARIA]. These features are used by authors creating accessible rich internet applications. Users often access the content using assistive technologies that rely on platform accessibility APIs to obtain and interact with information from the page. The WAI-ARIA User Agent Implementation Guide defines how implementations should expose content to accessibility APIs, helping to ensure that this information appears in a manner consistent with author intent. This document is part of the WAI-ARIA suite described in the ARIA Overview.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document is a First Public Working Draft by the Protocols & Formats Working Group of the Web Accessibility Initiative. It supports the Accessible Rich Internet Applications (WAI-ARIA) [ARIA] specification, providing information about how user agents should expose ARIA features to platform accessibility APIs. Implementers of mainstream user agents that work in concert with third party assistive technologies should follow the approaches in this document.
The Protocols and Formats Working Group has not yet decided whether the advice in this document should ultimately be normative, meaning user agents that conform to ARIA must conform to this document, or informative, meaning it provides advice that user agents should follow for interoperability, but may deviate from the advice when there is reason. At present, this document is not on the W3C Recommendation Track and is expected to become a Working Group Note.
Feedback on the information provided here is essential to the ultimate success of Rich Internet Applications that afford full access to their information and operations. The PFWG asks in particular:
Comments on this document may be sent to public-pfwg-comments@w3.org (Archive). Comments should be made by 24 March 2009, although comments arriving later may still be considered. In-progress updates to the document may be viewed in the publicly visible editors' draft.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. The group does not expect this document to become a W3C Recommendation. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
The disclosure obligations of the Participants of this group are described in the charter.
If a user agent already exposes static content via the accessibility API on a given platform, most of the remaining work to enable ARIA can be divided into three parts:
In general, ARIA properties should only affect how content is mapped to platform accessibility APIs. It should not affect the visual rendering of content or the behavior of mainstream desktop browsers, except when style sheets are deliberately keyed off of ARIA attributes as recommended in the specification. This allows one of the primary principles of ARIA to be upheld—that content still renders and behaves the same for the majority of users in legacy browsers which do not support ARIA.
Accessibility APIs covered by this document are:
Information on how to best expose ARIA to the Mac OS X Accessibility Protocol, UI Automation, or other accessibility APIs is not yet available, but would be appreciated, as would any other feedback on the information contained in this document. If you need to expose to other accessibility APIs, it is recommended closely with assistive technology developers.
The accessible tree and the DOM tree are parallel structures. Roughly speaking the accessible tree is a subset of the DOM tree. Accessible objects are created in the accessible tree for every DOM element that should be exposed to an assistive technology, either because it may fire an accessible event or because it has a property, relationship or feature which needs to be exposed. Generally if something can be trimmed out it will be, for reasons of performance and simplicity. For example, a <span> with just a style change and no semantics will not get its own accessible object, but the style change will be exposed through a "text attribute run" in the AccessibleText interface.
In addition to the normal accessible tree, ARIA requires that the elements also be exposed if they have one of the following properties:
aria-activedescendant
attribute. In either case it may become focused and need to fire a focus event.aria-hidden
in this list, since hidden elements are typically removed from the accessible object hierarchy anyway)aria-controls
, aria-describedby
, aria-flowto
, aria-labelledby
or aria-owns
)Objects that should be removed from the accessible hierarchy (including their descendants):
role="presentation"
before any other mappable role, and the element is not focusablerole="presentation"
, and the table cell is not focusableWhen descendant trimming occurs, the Accessible Hypertext interface should also not be exposed for the root object that remains. The descendants are removed because their presence confuses some assistive technologies that do not expect descendants for these roles (e.g. the JAWS virtual buffer would speak the accessible name twice or reveal the slider thumb as an image).
Note: in the following sections, Boolean states from IAccessible2 and ATK are marked in all-caps, e.g. FOCUSABLE
.
Enabling keyboard navigation in web applications is the first step toward making accessible web applications possible. There are two mechanisms that allow for accessible script widgets: tabindex
and aria-activedescendant
. Most other aspects of ARIA widget development depend on keyboard navigation functioning properly.
Assistive technologies often need to set the focus. For example, voice input software, onscreen keyboards and screen readers supply their own structured navigation modes, providing additional commands for moving to elements in a page. Both the user agent and web pages need to handle this gracefully. Script container widgets cannot expect that focus changes occur only from the keyboard or a mouse click. They need to listen for focus or aria-activedescendant
changes and update their state when that occurs.
User agents that support ARIA expand the usage of tabindex
, focus
, and blur
to allow them on all HTML elements. The HTML 5 Working Draft adopts this practice, so this usage is expected to be per specification in the next version of HTML.
In HTML 4 and earlier, only links and form controls participated in the tab order and could receive focus. It was not possible to set focus to other elements, even using script focus methods. While it was possible to include such elements in the tab order with tabindex
, it was not possible to make them focusable but not in the tab order. To work around this problem, user agents expand the scope and allowed values of the tabindex
attribute.
Essentially, any element such as a div
, span
or img
can be added to the default tab order by setting tabindex="0"
. In addition, any item with tabindex="-1"
can be focused via script or a mouse click, but isn't part of the default tab order.
The tabindex system provides one way to develop custom widgets which are keyboard accessible, from simple widgets like a slider to container widgets like a menubar, tree view or spreadsheet. This system works in older versions of Internet Explorer, as far back as IE 5.5.
The user agent implementation must to do the following to enable tabindex on all elements:
element.tabIndex
property.focus
and blur
methods should be added to the HTMLElement interface (available to script for every type of element).focus
and blur
events.:focus
receives a focus outline.keydown
event must also cancel the keypress
event, for purposes of compatibility with other browsers. This is necessary because authors supporting Internet Explorer must use keydown
events to process keystrokes, where keydown
but not keypress
events are fired for non-alphanumeric keys. As web page authors implement script control over the keyboard they need to be able to use keydown
but cancel the effect of consumed keystrokes such as arrow keys.FOCUSED
and FOCUSABLE
accessibility API states, and focus
accessibility API event for any element in the accessibility hierarchy, where appropriate.The HTML 5 spec documents what the extended behavior of tabindex
should be ([HTML5], Section 6.5.1). The Gecko documentation on what the behavior should be is in Key-navigable custom DHTML widgets. The documentation for IE's tabindex behavior is in MSDN: tabindex Property. Opera has some simple testcases.
The aria-activedescendant
property could also be used to enable keyboard accessibility on any type of ARIA element. It is often a more convenient way of creating container widget keyboard navigation (where the entire widget is in the tab order just once, but the user can use keystrokes to navigate to descendant items of the container).
Typical usage is described as follows: the author will use tabindex="0"
on the container element and aria-activedescendant
to point to the ID of the currently active descendant. The author, not the user agent, is responsible for styling the currently active descendant to show it has keyboard focus (not via :focus
since actual focus is on the container).
The user agent must do the following to implement aria-activedescendant
:
tabindex="0"
on all elements is still necessary for authors to use aria-activedescendant
system, because the container widget must be in the tab order.aria-activedescendant
which points to a valid ID, do not mark it as focused in the accessibility API (iow don't use the states FOCUSED
or FOCUSABLE
)aria-activedescendant
attribute changes on an element that currently has DOM focus, fire an accessibility API FOCUS
event on the new active descendant. If aria-activedescendant
is cleared or doesn't point to an element in the current document, then fire a focus event for the container object that had the attribute change.aria-activedescendant
attribute, apply the following states to the target to ensure the object is accessible:
FOCUSABLE
, if the element also has an ARIA role—because the aria-activedescendant
of the container can potentially point to it. It is not absolutely necessary to check this when there is no role, because real HTML elements that would be focused would already be focusable.ACTIVE
, whenever the container element sets aria-activedescendant
to match the ID of this descendantFOCUSED
, if ACTIVE
and the container widget with aria-activedescendant
has true DOM focusaria-activedescendant
, the implementation should change the value of aria-activedescendant
to point to that item.Note for authors: as you move focus to the next descendant, ensure that it is scrolled into view using scrollIntoView()([HTML5], Section 6.4).
Alternative input software needs to be able to set focus to items exposed as FOCUSABLE
. Screen readers, voice input software and on screen keyboards may set focus based on user commands implemented in that software. An MSAA-based AT does this via accSelect(SELFLAG_TAKEFOCUS) and in ATK this comes via AtkComponent::grab_focus.
aria-activedescendant
attribute present, then set DOM focus to that ancestor. If successful, then set aria-activedescendant
on the ancestor to the ID of the desired element.Note for authors: you will need an onfocus handler to enable alternative input. For example, when implementing a listbox
with focusable list items, don't assume that a mouse click or key press are the only ways a new list item may receive focus. Therefore, any direct style changes to the focused element should happen in the onfocus handler instead of the click and keypress handlers. For the same reason, when using aria-activedescendant
, watch for DOMAttrModifed
(onpropertychange
in IE) to react to changes to these attributes.
Where possible, ARIA semantics should be exposed through the standard mechanisms of the desktop accessibility API. For example, for ARIA widgets, compare how the widget is exposed in a similar desktop widget. In general most ARIA widget capabilities are exposed through the role, value, Boolean states and relations of the accessibility API.
User agents should notify assistive technology of state changes. Conversely, assistive technology notification of property changes depends on the method by which an assistive technology communicates with the user agent. For example, the aria-multiline
property is not something that changes frequently, whereas the aria-checked
state changes frequently in response to user input.
For the core accessibility API properties of role, name, states, value, etc. there is typically only one of each of them. If there is a conflict, ARIA always wins, because ARIA is essentially an override. In other words, if the native markup says there a link, but the ARIA markup says it is a button, then it should be exposed as a button.
When ARIA roles, states and properties don't directly map to an accessibility API, provide a mechanism to expose the raw ARIA data as a text string. User agents may always expose raw ARIA information through this API regardless of whether there is a direct mapping to an accessibility API.
ARIA also exposes new capabilities that desktop accessibility APIs do not currently cover. ARIA uses object attributes to expose semantics not traditionally found in accessibility APIs. Object attributes are name-value pairs that are loosely specified, and very flexible for exposing things that an accessibility API does not have a specific interface for. For example, the aria-live
attribute must be exposed via an object attribute because accessibility APIs have no such property available. Specific rules for exposing object attribute name-value pairs are described throughout this document, and rules for the general cases not covered are in States and Object Properties.
For accessibility APIs that do not have "object attributes" per se, it is useful to find a similar mechanism or develop a new interface to expose name/value pairs. Under the Mac OS X Accessibility Protocol, all getters are already simply name-value pairs and it is possible to expose new semantics whenever necessary. Keep in mind, this also requires working with the assistive technology developers to gain support for the new semantics.
In ARIA, the role attribute may indicate more than one role. The role value is an ordered set of space-separated tokens where each token must be a valid role token. ARIA includes some roles, such as landmarks and advanced widgets, that are not traditionally part of accessibility APIs. In addition, future versions of ARIA may allow for author-defined roles to be used in the role string. In that case, it is expected that a fallback role may be provided after the custom role, in the role string.
Platform accessibility APIs traditionally have had a finite set of predefined roles that are expected by assistive technologies on that platform. There may not always be a perfect match for an ARIA role to a role in the platform accessibility API.
Another difference is that in platform accessibility APIs, only one or two roles may be exposed through the traditional role mechanisms. In contrast, ARIA allows multiple roles to be exposed. Additional roles may be fallback roles. This may be a backup in case a custom role is unknown to some implementations, or it may be a landmark role. Because landmarks do not generally have mappings in platform accessibility APIs, they may occur anywhere within the role string without affecting how the first widget role is exposed.
The user agent should expose roles so that the standard role mechanism of the accessibility API provides the best-fit widget role, yet the entire role string is also available for parsing:
Dynamic role changes are considered an error in the WAI-ARIA specification, and are discussed in Error Handling.
EVENT_OBJECT_HIDE
and EVENT_OBJECT_SHOW
, with EVENT_OBJECT_REORDER
on the parent accessible objectARIA role | MSAA role | IAccessible2 role (if different from MSAA) | ATK role | NSAccessibility Role |
---|---|---|---|---|
"alert" | ROLE_SYSTEM_ALERT | ATK_ROLE_ALERT | ||
"alertdialog" | ROLE_SYSTEM_ALERT | ATK_ROLE_ALERT | ||
"application" | ROLE_SYSTEM_APPLICATION | ATK_ROLE_EMBEDDED | ||
"button" | ROLE_SYSTEM_PUSHBUTTON . If a "button" has the state aria-haspopup ="true" it should be exposed as a ROLE_SYSTEM_BUTTONMENU | If a "button" and aria-pressed is not undefined, it should be exposed in IA2 as IA2_ROLE_TOGGLE_BUTTON | ATK_ROLE_PUSH_BUTTON | NSAccessibilityButtonRole |
"checkbox" | ROLE_SYSTEM_CHECKBUTTON + object attribute checkable ="true" | ATK_ROLE_CHECK_BOX + object attribute checkable ="true" | NSAccessibilityCheckBoxRole | |
"columnheader" | ROLE_SYSTEM_COLUMNHEADER | ATK_ROLE_COLUMN_HEADER | ||
"combobox" | ROLE_SYSTEM_COMBOBOX + STATE_SYSTEM_HASPOPUP . If aria-expanded != "true", expose STATE_SYSTEM_COLLAPSED | ATK_ROLE_COMBO_BOX + ATK_STATE_EXPANDABLE + object attribute haspopup ="true" | NSAccessibilityComboBoxRole | |
"description" | No role mapping, use xml-roles | IA2_ROLE_TEXT_FRAME | ATK_ROLE_TEXT | |
"dialog" | ROLE_SYSTEM_DIALOG | ATK_ROLE_DIALOG | ||
"document" | ROLE_SYSTEM_DOCUMENT | ATK_ROLE_DOCUMENT_FRAME | ||
"grid" | ROLE_SYSTEM_TABLE | ATK_ROLE_TABLE | ||
"gridcell" | ROLE_SYSTEM_CELL | ATK_ROLE_TABLE_CELL | ||
"group" | ROLE_SYSTEM_GROUPING | ATK_ROLE_PANEL | NSAccessibilityGroupRole | |
"heading" | None, use xml-roles | IA2_ROLE_HEADING | ATK_ROLE_HEADING | |
"img" | ROLE_SYSTEM_GRAPHIC | ATK_ROLE_IMAGE | NSAccessibilityImageRole | |
"label" | ROLE_SYSTEM_STATICTEXT | IA2_ROLE_LABEL | ATK_ROLE_LABEL | |
"link" | ROLE_SYSTEM_LINK . Also, apply special rule to expose STATE_LINKED to link and all its descendants. | ATK_ROLE_LINK | NSAccessibilityLinkRole | |
"list" | ROLE_SYSTEM_LIST + STATE_SYSTEM_READONLY | ATK_ROLE_LIST | ||
"listbox" | ROLE_SYSTEM_LIST | ATK_ROLE_LIST . Special case: if a "listbox" has a parent or is owned by (via aria-owns ) a "combobox", it should be exposed with ATK_ROLE_MENU . | NSAccessibilityListRole | |
"listitem" | ROLE_SYSTEM_LISTITEM + STATE_SYSTEM_READONLY | ATK_ROLE_LISTITEM | ||
"marquee" | No role mapping, use xml-roles | ATK_ROLE_PANE | ||
"menu" | ROLE_SYSTEM_MENUPOPUP | ATK_ROLE_MENU . These objects should not be exposed for a submenu if there is a parent menu item spawning the submenu. | NSAccessibilityMenuRole | |
"menubar" | ROLE_SYSTEM_MENUBAR | ATK_ROLE_MENU_BAR | NSAccessibilityGroupRole | |
"menuitem" | ROLE_SYSTEM_MENUITEM | ATK_ROLE_MENU_ITEM
| If the option's parent has a If the option's parent has a | |
"menuitemcheckbox" | ROLE_SYSTEM_MENUITEM + object attribute checkable =true | IA2_ROLE_CHECK_MENU_ITEM + object attribute checkable="true" | ATK_ROLE_CHECK_MENU_ITEM + object attribute checkable ="true" | NSAccessibilityMenuItemRole |
"menuitemradio" | ROLE_SYSTEM_MENUITEM + object attribute checkable=true | IA2_ROLE_RADIO_MENU_ITEM + object attribute checkable="true" | ATK_ROLE_RADIO_MENU_ITEM + object attribute checkable ="true" | NSAccessibilityMenuItemRole |
"option" | ROLE_SYSTEM_LISTITEM + if aria-checked is not undefined, support object attribute "checkable "="true" | ATK_ROLE_LIST_ITEM
| If the option's parent has a If the option's parent has a | |
"presentation" | Do not expose this object unless it is focusable | Do not expose this object unless it is focusable | ||
"progressbar" | ROLE_SYSTEM_PROGRESSBAR + READONLY | ATK_ROLE_PROGRESS_BAR + READONLY | NSAccessibilityProgressIndicatorRole | |
"radio" | ROLE_SYSTEM_RADIOBUTTON | ATK_ROLE_RADIO_BUTTON | NSAccessibilityRadioButtonRole | |
"radiogroup" | ROLE_SYSTEM_GROUPING | ATK_ROLE_PANE | NSAccessibilityRadioGroupRole | |
"region" | ROLE_SYSTEM_PANE | ATK_ROLE_PANE | ||
"row" | ROLE_SYSTEM_ROW unless inside a "tree" or "treegrid", in which case ROLE_SYSTEM_OUTLINEITEM | ATK_ROLE_LIST_ITEM | ||
"rowheader" | ROLE_SYSTEM_ROWHEADER | ATK_ROLE_ROW_HEADER | ||
"section" | None, use xml-roles | IA2_ROLE_SECTION | ATK_ROLE_SECTION | |
"separator" | ROLE_SYSTEM_SEPARATOR | ATK_ROLE_SEPARATOR | ||
"slider" | ROLE_SYSTEM_SLIDER | ATK_ROLE_SLIDER | NSAccessibilitySliderRole | |
"spinbutton" | ROLE_SYSTEM_SPINBUTTON | ATK_ROLE_SPIN_BUTTON | NSAccessibilityProgressIndicatorRole | |
"status" | ROLE_SYSTEM_STATUSBAR | ATK_ROLE_STATUSBAR | ||
"tab" | ROLE_SYSTEM_PAGETAB . Expose SELECTED state if focus is inside tabpanel associated with aria-labelledby . | ATK_ROLE_PAGE_TAB . Expose SELECTED state if focus is inside tabpanel associated with aria-labelledby . | ||
"tablist" | ROLE_SYSTEM_PAGETABLIST | ATK_ROLE_PAGE_TAB_LIST | ||
"tabpanel" | ROLE_SYSTEM_PROPERTYPAGE | ATK_ROLE_SCROLL_PANE | ||
"textbox" | ROLE_SYSTEM_TEXT + IA2_STATE_SINGLE_LINE of aria-multiline is not "true" | ATK_ROLE_ENTRY + ATK_STATE_SINGLE_LINE of aria-multiline is not "true" | NSAccessibilityTextAreaRole | |
"toolbar" | ROLE_SYSTEM_TOOLBAR | ATK_ROLE_TOOL_BAR | ||
"tooltip" | ROLE_SYSTEM_TOOLTIP | ATK_ROLE_TOOL_TIP | ||
"tree" | ROLE_SYSTEM_OUTLINE | ATK_ROLE_TREE | ||
"treegrid" | ROLE_SYSTEM_OUTLINE | ATK_ROLE_TREE_TABLE | ||
"treeitem" | ROLE_SYSTEM_OUTLINEITEM + if aria-checked is not undefined, support object attribute "checkable "="true" | ATK_ROLE_LIST_ITEM + if aria-checked is not undefined, support object attribute "checkable "="true" |
This section describes how to expose additional states and object properties not covered in previous sections of this document. Where possible, API standard states are used. When that is not possible, object attributes (or a similar mechanism) is required.
VISIBLE
/INVISIBLE
, SHOWING
/OFFSCREEN
, etc. This typically is done in the same way as for ordinary elements that do not have ARIA attributes present. For FOCUSABLE
/FOCUSED
, it may be affected by aria-activedescendant
—see the rules in aria-activedescendant.aria-required
, but only some roles such as role="checkbox" support the aria-checked
property. To compute the properties see the table below.ARIA property mapping rule table:
Important Note: any ARIA property of type Boolean or NMTOKEN is undefined if the ARIA attribute is not present, or is set to the zero-length string or "undefined". This does not affect properties of type string, decimal, IDREF or IDREFS.
Also, ensure that states and properties which are not global are only computed on elements with roles that support them.
ARIA state | What to expose |
---|---|
aria-activedescendant | Expose as described in aria-activedescendant, and set appropriately when the AT pushes focus changes in a container with this attribute not undefined as described in Handling focus changes from the AT. Universal Access: if |
aria-atomic | If not undefined and not false expose atomic="true". In addition, expose container-atomic="true" on all descendants as well as |
aria-autocomplete |
|
aria-busy |
|
aria-checked |
|
aria-controls | Expose the relations as described in Relations |
aria-describedby | Expose the relations as described in Relations
|
aria-disabled |
|
aria-dropeffect | Expose as object attribute "dropeffect" |
aria-expanded |
|
aria-flowto | Expose the relations as described in Relations |
aria-hidden | This is not used in mapping to platform accessibility APIs. Instead, use information from the layout system to determine if the element is hidden or not. Advisory: it is incorrect use of ARIA if an element with aria-hidden="true" is visible. The aria-hidden property is exposed only so that DOM-based assistive technologies can be informed of visibility changes. However, the layout will be able to provide the most complete set of all truly hidden nodes. |
aria-invalid | If "false", clear INVALID_ENTRY or equivalent state, else if not "false" and not undefined, then set INVALID_ENTRY In addition, if not "false" or undefined, expose the value as a text attribute (not object attribute). Current possible values are are "true", "spelling" or "grammar". |
aria-haspopup | If "false", clear the
ROLE_SYSTEM_BUTTONMENU |
aria-label | Expose in accessible name |
aria-labelledby | Expose the relations as described in Relations as well as in accessible name |
aria-level | Expose value in"level" object attribute and in IAccessible2's groupPosition . May affect RELATION_NODE_CHILD_OF when used on a tree item. See section Group Position. |
aria-live | If not undefined, expose the value in an object attribute called "live". Expose a "container-live" object attribute with the value on all descendants as described in Changes to document content or node visibility. |
aria-multiline | If "false" clear the Universal Access: report "textbox" role as AXTextArea |
aria-multiselectable | If "false" clear the |
aria-owns | Expose the relations as described in Relations |
aria-pressed |
|
aria-posinset | Expose value in "posinset" object attribute and in IAccessible2's groupPosition |
aria-readonly | In MSAA, expose as If on an element that is editable, e.g. an |
aria-relevant | If not undefined, expose the value in an object attribute called "relevant". Expose a "container-relevant" object attribute with the value on all descendants as described in Changes to document content or node visibility. |
aria-required | Expose as REQUIRED state |
aria-selected |
|
aria-setsize | Expose value in "setsize" object attribute and in IAccessible2's groupPosition |
aria-sort | Expose value in "sort" object attribute |
aria-valuemax | Expose via AccessibleValue interface as described in Value Universal Access: set AXMaxValue attribute |
aria-valuemin | Expose via AccessibleValue interface as described in Value Universal Access: set AXMinValue attribute |
aria-valuenow | Expose via AccessibleValue interface as described in Value, and set when the AT uses the Value interface to set the value on an element that is not Universal Access: set AXValue and post NSAccessibilityValueChangedNotification if necessary |
aria-valuetext | Expose in "valuetext" object attribute as described in Value [ Aaron: this seems correct, is it? ... Universal Access: set NSAccessibilityValueDescriptionAttribute to valuetext string ] |
For dynamic ARIA property changes, expose an event such as a state change event to indicate the change occurred. For simplicity and performance the user agent may trim out change events for properties that assistive technologies typically ignore changes in. However, at a minimum, state change events should be fired for changes in:
aria-disabled
: this will affect ENABLED
and SENSITIVE
statesaria-checked
or aria-pressed
: this will affect the CHECKED
state. A state change for MIXED
/INDETERMINATE
should also be fired when the value changes to or from "mixed".aria-invalid
: this will affect the INVALID_ENTRY
state (be careful, the INVALID state in APIs means no valid state, which is different)aria-expanded
, aria-readonly
, aria-required
: these will affect the states of similar names in the accessibility APIsOther types of changes:
aria-activedescendant
changes affect focus events as described in aria-activedescendantaria-valuenow
changes affect value change events as described in Valuearia-multiselectable
changes should cause the destruction and recreation of a new accessible object for the element, because it is a major change where the interfaces exposed via accessibility APIs change as well.aria-selected
changes should affect selection events as described in SelectionThis computation is referred to by both the Name and Description computations described after it.
To compute the text equivalent for an element:
If the current node is hidden and not currently pointed to directly by an aria-labelledby
or aria-describedby
used in this text equivalent traversal, then, skip the node.
Else if the current node is a text node, append the text contents. It is generally preferable to append the rendered text contents, where whitespace is normalized.
Else if aria-label
is present, use the value of the aria-label
property for the text equivalent of this node.
Else if aria-labelledby
is present, and this node is not already part of an aria-labelledby
or accessible name calculation, then process aria-labelledby
to generate the text equivalent of this node. Within the aria-labelledby
value, process the IDs in the order they occur and ignore IDs in that are not specified on an element in the document. For each ID's associated element, implement this text equivalent computation starting with step 1, appending the results to the total text equivalent result string as they are collected.
For example:
<button aria-labelledby="span" id="btn" /> Text equivalent = "text"—we follow aria-labelledby
because this is root node for text equivalent calculation
<button aria-labelledby="btn" /> No text equivalent, because we follow 1st aria-labelledby
but not the 2nd since it is not the root node for the name calculation
<span id="span">text</span>
Else if the native markup provides a text equivalent, append it to the text equivalent. An example of a native markup text equivalent is alt for HTML <img> or a label from <label for>. However, do not use markup for tooltips here—they are used basically as a last resort under item h.
Append the current user-entered value of this node to the text equivalent. However, in order to avoid redundant presentation of the same text, do not append this text if it will be the first or last part of a text equivalent calculation for the same node that it came from. For example:
<span role="checkbox" id="cb">Want <input type="text" aria-labelledby="cb"> for breakfast</span>
<span role="checkbox" id="cb"><input type="text" aria-labelledby="cb"> wants breakfast</span>
<span role="checkbox" id="cb">I want to eat <input type="text" aria-labelledby="cb"></span>
Results:
The text equivalent for <span role="checkbox"> elements below always uses the value from the inner text field, because the text field is part of the text equivalent computation for a different node (the <span role="checkbox>) .
For the text equivalent for <input>'s, only case #1 below uses the value for its own label, it's in the middle of the text equivalent calculation. Because the value occurs in the middle of the text equivalent, it is necessary to present its placement within the context of the larger text equivalent.
If the text equivalent for this node is empty, and either the current node's role allows "Name From: subtree" or the current node is not a control but is part of a label or description, recursively implement this name computation for each child, starting with step 1, appending the results to the total name result string as they are collected. If this recursion only produces white space, reduce it down to an empty string, and use the following rule instead.
Else if the text description for this node is still empty, get the name from tooltip for the current node if any (e.g. title attribute in HTML, tooltiptext attribute or tooltip attribute in XUL) of the current node.
To compute the accessible name for an element, start with an empty string:
If aria-label
is not present but aria-labelledby
is present, collect the name using the text equivalent computation on the elements pointed to by aria-labelledby
. Process the IDs in aria-labelledby
in the order they occur. Ignore IDs that are not specified on an element in the document.
Else this means that aria-labelledby
will not be used, and the accessible name should be computed using the text equivalent computation on the current element.
If the element is an <img> and the text equivalent is empty, then check for the presence of any labeling attribute, specifically aria-label
, aria-labelledby
, alt or title. The presence of any of these would indicate the author's intention to set an empty text equivalent for decorative or redundant image content. If none of these attributes are present, this indicates the author simply did not provide an accessible label for the image, and the implementation should return an accessible name of NULL instead of "". This hints to the AT to do its own heuristic processing to repair the missing accessible name.
To compute the accessible description for an element, start with an empty string:
If aria-describedby
is present, collect the description from the elements pointed to by aria-describedby
. Process the IDs in aria-describedby
in the order they occur. Ignore IDs that are not specified on an element in the document. For each ID use the text equivalent computation.
When the aria-valuenow
attribute is supported for a role used on the element, the AccessibleValue interface must be supported on the accessible object to expose. The aria-valuemin
and aria-valuemax
should be exposed via the AccessibleValue interface.
There may also be a text equivalent for the numerical value, which is set via the aria-valuetext
property. That should be exposed via a "valuetext" object attribute, or a similar mechanism if object attributes are not available in the API. When no aria-valuetext
is present, then expose a string version of the aria-valuenow
in the valuetext object attribute.
In addition, for MSAA, the string should also be exposed via IAccessible::get_accValue
.
Changes to aria-valuenow
should be exposed via value change events. [davidb: is there any event throttling that should be applied here, or is the cost not too high? (see related group post)]
If the value is not set on a control that requires value, then current value should return an error. This is a valid condition for progressbar
, where the current value could be indeterminate.
The AcessibleValue allows values to be set. If the object is not readonly or disabled, it should allow this and the UA should set aria-valuenow
to reflect the new value. It is not possible to alter the value in a progress meter since it is always readonly. The implementation should reject values which are less than the aria-valuemin
or greater than the aria-valuemax
. If the value cannot be set because the object is readonly
or disabled
, the new value would be out of bounds, the implementation should throw an exception rather than set the value.
Note to authors: a script widget which supports aria-valuenow
and is not readonly
or disabled
should listen for aria-valuenow
changes and when it changes, reset the internal state, the aria-valuetext
(if used) and the visual state of the widget.
All relations are globally applicable to any element, so it is not important to check the role before computing them. Relationship attributes use an ID list (space separated list of IDs). A relationship ID matches the element having that ID, that is returned by getElementById
with the ID as an argument.
Exposing forward relations:
aria-controls
maps to RELATION_CONTROLLER_FOR
aria-describedby
maps to RELATION_DESCRIBED_BY
aria-flowto
maps to RELATION_FLOW_TO
aria-labelledby
maps to RELATION_LABELLED_BY
aria-owns
has no standard API relation mapping in ATK/AT-SPI or IAccessible2 Computing reverse relations:
aria-controls
points to the element: expose RELATION_CONTROLLED_BY
aria-describedby
points to the element: expose RELATION_DESCRIPTION_FOR
aria-flowto
points to the element: expose RELATION_FLOW_FROM
aria-labelledby
points to the element: expose RELATION_LABEL_FOR
aria-owns
points to the element: expose RELATION_NODE_CHILD_OF
If both aria-labelledby
and HTML <label for=> are used, the ARIA relation wins and the HTML label relation is ignored.
Computing RELATION_NODE_CHILD_OF
for role="treeitem", when aria-owns
is not used:
aria-level
, then walk backwards in the tree until a treeitem is found with a lower aria-level
, and point to that. If the top of the tree is reached, then point to the tree itself.Computing RELATION_MEMBER_OF
from aria-atomic
:
RELATION_MEMBER_OF
relation to point to the ancestor that sets aria-atomic="true".The object attributes "posinset
", "setsize
" and "level
" should be exposed when the equivalent ARIA properties are supported by a role used on the element. In addition, on IAccessible2 the same information must be exposed via IAccessible2::groupPosition
.
Computing the level if not provided:
aria-level
is not provided by the author, it must be computed by following the explicit or computed RELATION_NODE_CHILD_OF
as described in Relations.When computing posinset and setsize if not provided:
These properties are all 1-based. When the object property is not present or holds a value of "0", it indicates the property is not computed or not supported.
Because these values are 1-based, the current item must be included in the computation. For posinset, add items only if they are before the current item in the DOM. For setsize, also add items after the current item in the DOM.
In general the base markup should determine what interfaces are exposed for an accessible object. However, in the following cases ARIA markup changes which interfaces should be exposed:
AccessibleValue
: as discussed in Value, the value interface should be exposed for objects with an aria-valuenow
property when one of the roles on the elements supports that. Because the Value interface allows values to be set, aria-valuenow
is really read/write. The browser needs to set aria-valuenow
if the value is changed to a valid value, and the current element is not readonly or disabled. Note to authors: anything that implements valuenow needs to watch for on DOMAttrChanged
(onpropertychange
in IE) and react to it.AccessibleTable
: should be exposed for role="grid" and role="treegrid" (XXX note: not done in Mozilla—known bug)AccessibleSelection
: should be exposed when a role supports aria-multiselectable
, and aria-multiselectable
="true"AccessibleHypertext
: this should not be exposed if the elements descendants have been trimmed off based on the role. See 11.3.2.1 for which roles have their subtrees trimmed.Although it is not an ARIA-specific issue, for the purposes of accessible web applications it is worth mentioning some additionally useful rules for exposing interfaces:
AccessibleAction
: should at least be exposed for anything with a "click" handler, although future versions of ARIA may bring more precision to the handling of actions. Also need to support doDefaultAction in MSAA (same as action #0)—this maps to a click.AccessibleEditabletext
: should be exposed for any region made editable via contenteditable or designModeActions are exposed by the following rules
ARIA Role | Action |
alert | no |
alertdialog | no |
application | no |
article | no |
button | click |
checkbox | check/uncheck |
columnheader | no |
combobox | open/close |
description | no |
dialog | no |
document | no |
grid | no |
gridcell | no |
group | no |
heading | no |
img | no |
label | no |
link | jump |
list | no |
listbox | no |
listitem | select/unselect if parent role is listbox |
math | no |
menu | no |
menubar | no |
menuitem | click |
menuitemcheckbox | click |
menuitemradio | click |
option | select/unselect |
presentation | no |
progressbar | no |
radio | select |
region | no |
row | no |
rowheader | no |
section | no |
separator | no |
slider | no |
spinbutton | no |
status | no |
tab | switch |
tablist | no |
tabpanel | no |
textbox | activate |
toolbar | no |
tooltip | no |
tree | no |
treegrid | no |
treeitem | activate + expand/collapse |
Processing document changes is important regardless of ARIA. We document how to do it here, however, because it is so crucial to enable the AJAX and other use cases that often go along with ARIA markup.
Fire these events for text changes:
IA2_EVENT_TEXT_REMOVED
(IA2) and text_changed:delete (ATK)IA2_EVENT_TEXT_INSERTED
(IA2) and text_changed:insert (ATK)Fire these events for node changes where the node in question is an element and has an accessible object:
EVENT_OBJECT_HIDE
(MSAA) and children_changed:remove (ATK). The MSAA event called EVENT_OBJECT_DESTROY
is not used because this has a history of stability issues and ATs avoid it. In any case, from the user's point of view, there is no difference between something that is hidden or destroyed.EVENT_OBJECT_SHOW
(MSAA) and children_changed:add (ATK).For node changes where the node is not an element or has no accessible object:
When firing any of the above-mentioned change events, it is very useful to provide information about whether the change was caused by user input (as opposed to a timeout initiated from the page load, etc.). This allows the AT to have different rules for presenting changes from the real world as opposed to from user action. Mouse hovers are not considered explicit user input because they can occur from accidental bumps of the mouse.
To expose whether a change occurred from user input:
Exposing additional useful information about the context of the change:
aria-atomic
="true" (if any).container-live
, container-channel
, container-relevant
, container-busy
, container-atomic
object attributes should be exposed on the accessible event object, providing the computed value for the related ARIA properties. The computed value is the value of the closest ancestor. It is recommended to not expose the object attribute if the default value is used.Additional MSAA events may be necessary:
ROLE_SYSTEM_ALERT
, then an EVENT_SYSTEM_ALERT
event should be fired for the alert. The alert role has an implied value of "assertive" for the aria-live
property.There are two cases for selection:
In the single selection case, it is not always necessary to manage selection events and states separate from focus, since selection mirrors focus. One exception is for tab lists. In the case of a tab, if either the tab or its associated tabpanel has focus, then the tab is considered to be SELECTED
. To implement this: the user agent can walk up the parent chain from the focus until it finds the a tabpanel, then traverse the aria-labelledby
relation from the tabpanel to the related tab, and mark the found tab as focused.
The multiple selection case occurs when aria-multiselectable
="true" on an element with a role that supports that property. There are several important aspects:
MULTISELECTABLE
and, in MSAA, it is also EXTSELECTABLE
aria-multiselectable
. The selection interface can be used by an AT to actually set the selection on a descendant. This should fail for the specified descendant if aria-selected
is undefined, which indicates the element is not SELECTABLE
. It should also fail if the specified descendant is DISABLED
or READONLY
for any reason. When clearing selection on an item, set aria-selected
="false" but do not remove the attribute, so that it is still SELECTABLE
. Note to authors: scripts need to watch for mutations to aria-selected
, since selection may be caused by an AT and not the mouse or keyboard.aria-selected
changes on a descendant, as follows:Scenario | MSAA/IA2 | ATK/AT-SPI |
---|---|---|
Toggle aria-selected | EVENT_OBJECT_SELECTIONADD /EVENT_OBJECT_SELECTIONREMOVE on the current container + EVENT_OBJECT_STATECHANGE on the item | object::selection_changed + atk_object_notify_state_change on the item |
Selection follows focus | EVENT_OBJECT_SELECTION then state change event on newly focused item, but arrange events so state change doesn't occur on focused item, to avoid extra selection change announcements | object:selection_changed + atk_object_notify_state_change , but arrange events so state change doesn't occur on focused item, to avoid extra selection change announcements |
Select or deselect many items at once: | EVENT_OBJECT_SELECTIONWITHIN is all that is necessary. The state change events may be trimmed out for performance. | object:selection_changed . The state change events may be trimmed out for performance |
Under MSAA special events are required whenever a menu is opened or closed. These events must be nested and symmetrical:
EVENT_SYSTEM_MENUSTART
when a menu in a menubar is opened. This is triggered when focus goes to a menuitem and menu mode is not currently active, but it must be fired before any EVENT_SYSTEM_MENUPOPUPSTART
events. The menubar must be either in the natural parent chain or or in the one caused by aria-owns
(use RELATION_NODE_CHILD_OF
impl to go to aria-owns
ancestor).EVENT_SYSTEM_MENUPOPUPSTART
when a menu popup is made visible. This is triggered when a menu is made visible, but should only be fired once until the menu is closed and reopened again. Care should be taken to check descendants for role="menu" when any subtree is made visible. The menu role might not be on the root node of the change.EVENT_SYSTEM_MENUPOPUPSTART
.EVENT_SYSTEM_MENUPOPUPEND
when a menu popup is hidden. This should only be fired for an accessible menu object when an EVENT_SYSTEM_MENUPOPUPSTART
was fired for it, and it should only be fired once in that case. Care should be taken to check descendants for role="menu" when a subtree is hidden.EVENT_SYSTEM_MENUEND
when in menubar mode (a MENUSTART was fired) and either all menus in a menubar are closed or focus goes somewhere other than a menuitem (such as a control in a dialog).Because screen readers on Windows will typically ignore focus events while menus are opened, it is important to fire the symmetrical EVENT_SYSTEM_MENUPOPUPEND
followed by a EVENT_SYSTEM_MENUEND when something other than a menu received focus (e.g. selecting the menu option opened a dialog). In fact, screen readers can become quite confused if the correct ending menu events are not fired.
That said, perfectly symmetrical events are difficult to achieve. Because menus can be made visible hidden using a variety of techniques, it is advisable that an implementation keep track of the menu events fired and ensure symmetrization.
frame
and iframe
elementsComputing the accessible name for an outer document accessible:
Computing the accessible name for an inner document accessible:
aria-labelledby
from the <frame> or <iframe>. If the name is still empty, use the title attribute from the <frame> or <iframe>.aria-labelledby
on the document's root ARIA node. If it is still empty use the title attribute on the root ARIA node.Computing the accessible description for an inner document accessible:
aria-describedby
from the <frame> or <iframe>.aria-describedby
on the document's root ARIA node.Computing container-foo on any node in a sub document: For container-live
, container-atomic
, container-relevant
, container-channel
and container-busy
, inner nodes override outer nodes from within the same documment, because the inner subtree is the more relevant context. However, outer documents override inner documents, because the outer document author may be different and may wish to define the context for a live iframe. Therefore:
aria-live
, aria-atomic
, aria-relevant
, and aria-busy
into the container-[property] object attributeComputing other properties for an inner document accessible:
aria-selected
, aria-valuenow
, aria-valuetext
, aria-activedescendant
), use the ARIA markup on the root ARIA node onlySupport for attribute selectors must include ARIA attributes. For example, .fooMenuItem['aria-haspop=true'] should select all elements with class "fooMenuItem", and ARIA attribute "aria-haspopup
" with value true. The presentation must be updated for dynamic changes to ARIA attributes. This allows authors to match styling with ARIA semantics.
aria-controls
=”elem1”, “elem1” is the target element.Q: What happens if an invalid ID is specified for an ARIA property?
A: The UA will ignore the ID.
Q: What if the ARIA property contains a mixture of valid and invalid IDs?
A: The UA will return only the objects corresponding to the valid IDs.
Q: What if there is more than one element with the same ID?
A: The first element found with the given ID will be what is used. The behavior will be the same as getElementById, and it is the web author’s responsibility to ensure uniqueness of IDs.
Q: What if the same element is specified multiple times in a single ARIA relation of type IDREFS?
A: [Might need to reword this, I am assuming the return is an array of pointers to accessible objects] The UA will return multiple pointers to the same object.
Q: What happens if more than one ID is specified (space-separated list) for a property that is a single IDREF?
A: The UA will use the whole string (without splitting on spaces) and try to look up an element that has that ID. For instance aria-activedescendant
="foo bar" would match id="foo bar".
[IE-specific] Q: What if the author is using the “name” attribute instead of “id”, since they were interchangeable in IE7?
A: IE will only match on the “id” attribute, regardless of the version of the document. We believe that matching only on the “id” attribute is the correct behavior.
Q: What if a non-numeric value is specified for a decimal type?
A: If asking for the string version of the property, the UA will simply return the string specified by the author. However, if a decimal is specifically requested, the UA will fail to convert the string to a decimal and return a default value.
In general, UAs do not do much validation of ARIA properties. Some minor validation may occur on request, such as making sure valid IDs are specified for ARIA relations, and enforcing things like aria-posinset
being within 1 and aria-setsize
, inclusive. UAs are not responsible for logical validation, such as the following:
aria-activedescendant
being a DOM-descendant of the element with the relation.Q. What happens if the author uses an abstract role, or a role that does not map to a standard role for the platform accessibility API?
A: This is defined in the spec:
http://www.w3.org/TR/2009/WD-wai-aria-20090224/#ua_role_identify If a given role in the role attribute is abstract or has no mapping, skip that role. If no known role is found in the role attirbute, the UA will just act as if the role attribute was absent except it would still expose the role attribute's value in the xml-roles object attribute.
Q. What happens if the author changes the role of an element dynamically?
A. This is considered incorrect practice by the ARIA specification, can cause changes in what accessible interfaces need to be supported by an object, and is unexpected by ATs. Therefore, the least expensive way to handle dynamic role changes is used: fire the appropriate invalidation events for object with the role change, so that the AT will update its cache or virtual buffer. The relevant invalidation events are:
EVENT_OBJECT_HIDE
and EVENT_OBJECT_SHOW
, with EVENT_OBJECT_REORDER
on the parent accessible objectQ. Some ARIA properties are not global, and are only supported on certain roles. What should be mapped when a dependent ARIA property is used where it is not supported?
A. The user agent should act as if the ARIA property is absent, and not not map the given ARIA property through the platform accessibility API. For example, aria-checked
should not be exposed as CHECKED
on <div role="grid">
Q. What should be exposed to platform accesibility APIs when an ARIA property contains an unknown or disallowed value?
A.1 When exposing as an object attribute, expose the unknown value—do not vet it against possible values.
A.2 When exposing as a platform API Boolean state, treat "", "undefined" or no attribute present as false. Treat any other value as true.
A.3 Otherwise, ignore the value and treat the property as not present
Q. What should be exposed to platform accessibility APIs when an unknown ARIA property is used?
A. Expose an object attribute with the same name, with the "aria-" prefix removed. The object attribute's value should be equal to the ARIA property's value. This will help with forward compatibility with new ARIA properties in future versions.
Q. What if aria-hidden
does not match the reality of whether a node is visible or not?
A. This error condition does not even need to be checked for, because aria-hidden
is not necessary when a layout API provides more complete information. Advisory: it is incorrect use of ARIA if an element with aria-hidden
="true" is visible. The aria-hidden
property is exposed only so that DOM-based assistive technologies can be informed of visibility changes. Since layout APIs will be able to provide the most complete set of all truly hidden nodes, they should be used instead of the aria-hidden
attribute.
Q. If an AT uses a platform accessibility API setter to change aria-valuenow
, should the user agent ensure that the new value is within the bounds set by aria-valuemin
and aria-valuemax
?
A. Yes. Do not set the value if it is out of bounds. Note, however, that it is still the final responsibility of the web application to ensure the validity of user data.
Q. If an AT uses a platform accessibility API getter to get aria-valuenow
, should the user agent ensure that it is within the bounds set by aria-valuemin
and aria-valuemax
?
A. No, simply expose the aria-valuenow
whether it is out of bounds or not.
Q. What if an element has the aria-valuetext
property set, but not aria-valuenow
?
A. Expose the valuetext as defined in this guide, but return an error for any value getter that only returns a numeric type
Q. If an AT uses a platform accessibility API setter to change aria-valuenow
, should the user agent ensure that the current element is not disabled or readonly?
A. Yes. Do not set the value if the current element is disabled or readonly
Q. If an AT uses the platform accessibility API to change whether an element is selected, should the user agent ensure that the element is not disabled?
A. Yes. Do not set or clear the selection if the current element is disabled (although it is okay to change the selection for readonly elements)
Q. Should the user agent check whether aria-activedescendant
actually points to a descendant or not?
A. No
Q. What if aria-level
, aria-setsize
or aria-posinset
are 0 or negative?
A. Return 1
Q. What if aria-posinset
is larger than aria-setsize
?
A. Return aria-setsize
in place of aria-posinset
Q. What if a required aria property (i.e. required for a given role) is missing for a given widget?
A.
This section is informative.
This section is informative.
This section is informative.
The following people contributed to the development of this document.
Special thanks to Aaron Leventhal for effort and insight as he implemented a working prototype of accessibility API bindings.
Simon Bates, Judy Brewer (W3C/MIT), Christian Cohrs, Becky Gibson (IBM), Alfred S. Gilman, Andres Gonzalez (Adobe), Jeff Grimes (Oracle), Barbara Hartel, Earl Johnson (Sun), Jael Kurz, Linda Mao (Microsoft), Shane McCarron (ApTest), Dave Pawson (RNIB), Henri Sivonen (Mozilla), Vitaly Sourikov, Mike Squillace (IBM), Ryan Williams (Oracle), Tom Wlodkowski.
This publication has been funded in part with Federal funds from the U.S. Department of Education, National Institute on Disability and Rehabilitation Research (NIDRR) under contract number ED05CO0039. The content of this publication does not necessarily reflect the views or policies of the U.S. Department of Education, nor does mention of trade names, commercial products, or organizations imply endorsement by the U.S. Government.