Copyright © 2008 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
@@ 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 is an Editor's Draft of the Protocols and Formats Working Group. It is not stable and may change at any time. Implementors should not use this for anything other than experimental implementations.
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 anything other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. 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. 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.
Note: in the following sections, boolean states from IAccessible2 and ATK are marked in all-caps, e.g. FOCUSABLE
.
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:
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.
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. |
| 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 (XXX Mozilla todo). | 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 group role, then role="menuitem" maps to NSAccessibilityMenuButtonRole If the option's parent has a menu role, then role="menuitem" maps to NSAccessibilityMenuItemRole | |
"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 menu role, then role="option" maps to NSAccessibilityMenuItemRole If the option's parent has a list box role, then role="option" maps to NSAccessibilityStaticTextRole | |
"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 "" 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 AXFocused is true, post "NSAccessibilityFocusedUIElementChangedNotification" notification when |
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-channel | If "notify", expose channel="notify" and container-channel="notify" on all descendants as described in Changes to document content or node visibility. |
aria-checked |
|
aria-controls | Expose the relations as described in Relations |
aria-datatype | Expose as object attribute "datatype" |
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". |
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 occured. For simplicity and performance the user agent may trim out change events for properties that assistive technologies typically ignore changes in. However, at a miminum, 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 acessibility 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:
aria-labelledby
or aria-describedby
used in this text equivalent traversal, then, skip the node.aria-label
is present, use the value of the aria-label
property for the text equivalent of this node.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 equivalresult string as they are collected.aria-labelledby
because this is root node for text equivalent calculation -->aria-labelledby
but not the 2nd since it is not the root node for the name calculation -->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 labelling 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 valuemin or greater than the 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 JavaScript 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 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 IAccessible2Computing 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:
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.aria-multiselectable
, and aria-multiselectable
="true"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:
Actions 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).Additional MSAA events may be necessary:
ROLE_SYSTEM_ALERT
, then an EVENT_SYSTEM_ALERT
event should be fired for the alert.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.
Computing 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
, aria-channel
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-haspop
" 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/WAI/PF/aria/#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 vett 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.
Most errors that occur due to ARIA are not propagated to callers. For example, finding an invalid ID in a list of IDREFS is not a reason to return an error code to the caller. Errors that can propagate are specific to certain ARIA properties.
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), 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.