2. Notes on ARIA use in HTML๐
2.1 First rule of ARIA use๐
If you can use a native HTML element [HTML51] or attribute with the semantics and behaviour you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.
Under what circumstances may this not be possible?
- If the feature is available in HTML [HTML51] but it is not implemented or it is implemented, but accessibility support is not.
- If the visual design constraints rule out the use of a particular native element, because the element cannot be styled as required.
- If the feature is not currently available in HTML.
2.2 Second rule of ARIA use๐
Do not change native semantics, unless you really have to.
For example: Developer wants to build a heading that's a tab.
Do not do this:
<h2 role=tab>heading tab</h2>
Do this:
<div role=tab><h2>heading tab</h2></div>
If a non interactive element is used as the basis for an interactive element, developers have to add the semantics using ARIA and the appropriate interaction behaviour using scripting. In the case of a button, for example, it is much better and easier to Just use a (native HTML) button.
It is OK to use native HTML elements, that have similar semantics to ARIA roles used, for fallback. For example, using HTML list elements for the skeleton of an ARIA enabled, scripted tree widget.
2.3 Third rule of ARIA use๐
All interactive ARIA controls must be usable with the keyboard.
If you create a widget that a user can click or tap or drag or drop or slide or scroll, a user must also be able to navigate to the widget and perform an equivalent action using the keyboard.
All interactive widgets must be scripted to respond to standard key strokes or key stroke combinations where applicable.
For example, if using role=button
the element must be able to receive focus and a user must be able to activate the action associated with the element using both the enter (on WIN OS) or return (MAC OS) and the space key.
Refer to the Design Patterns and Widgets and Developing a Keyboard Interface sections of [wai-aria-practices-1.1]
2.4 Fourth rule of ARIA use๐
Do not use role="presentation"
or aria-hidden="true"
on a visible focusable element .
Using either of these on a visible focusable element will result in some users focusing on 'nothing'.
Do not do this:
<button role=presentation>press me</button>
Do not do this:
<button aria-hidden="true">press me</button>
If an interactive element cannot be seen or interacted with, then you can apply aria-hidden
, for example:
button {visibility:hidden}
<button aria-hidden="true">press me</button>
If an interactive element is hidden using display:none
, it will also be removed from the accessibility tree, which makes the addition of aria-hidden="true"
unnecessary.
2.5 Fifth rule of ARIA use๐
All interactive elements must have an accessible name.
An interactive element only has an accessible name when its Accessibility API accessible name (or equivalent) property has a value.
For example, the input type=text
in the code example below has a visible label 'user name' , but no accessible name:
user name <input type="text">
or
<!-- label element used, but not associated with the control
it is supposed to label -->
<label>user name</label> <input type="text">
The control's MSAA accName
property is empty:
In comparison, the input type=text
in the code example below has a visible label 'user name' and an accessible name. This example has an accessible name because the input
element is a labelable element and the label
element is used correctly to associate the label text with the input.
<!-- Note: use of for/id or wrapping label around text
and control methods will result in an accessible name -->
<label>user name <input type="text"></label>
or
<label for="uname">user name</label> <input type="text" id="uname">
The control's MSAA accName
property has a value of "user name":
The label
element cannot be used to provide an accessible name for custom controls, unless the label
is referencing a native HTML labelable element.
<!-- HTML input element with combox role -->
<label>
user name <input type="text" role="combobox">
</label>
The control's MSAA accName
property has a value of "user name":
A div
element regardless of what role is assigned is not a HTML labelable element.
<!-- HTML div element with combox role -->
<label>
user name <div role="combobox"></div>
</label>
The control's MSAA accName
property is empty:
5th rule is a work in progress
2.6 What does adding a role do to the native semantics?๐
Adding an ARIA role overrides the native role semantics in the accessibility tree which is reported via the accessibility API, and therefore ARIA indirectly affects what is reported to a screen reader or other assistive technology.
For example, this code in the HTML tree:
<h1 role=button>text</h1>
Becomes this in the accessibility tree:
What adding a role does not do๐
Adding an ARIA role will not make an element look or act differently for people not using assistive technology. It does not change the behaviours, states and properties of the host element but only the native role semantics.
For example, this code in the HTML tree:
<button role=heading aria-level=1>text</button>
Becomes this in the accessibility tree:
But it can still be pressed, it is still in the default tab order, still looks like a button and still triggers any associated actions when pressed. That's why it is a HTML5 conformance error to change a button into a heading.
Note: Changing the role
of an element does not add behaviors, properties or states to the role
used. ARIA does not change the way it looks or acts in a browser. For instance, when links are used to behave like buttons, adding role=button
alone is not sufficient. It will also be necessary to make act like a button, by including a key event handler that listens for the space key which native buttons do, because native buttons can be activated using the enter key or the spacebar.
2.7 Add ARIA inline or via script?๐
If the ARIA role or aria-* attribute does not rely on scripting to provide interaction behaviour, then it is safe to include the ARIA markup inline. For example, it is fine to add ARIA landmark roles or ARIA labelling and describing attributes inline.
If the content and interaction is only supported in a scripting-enabled browsing context, i.e. Google docs (its applications require JavaScript enabled to work), it is also safe to include the ARIA markup inline as the application simply will not work (for anyone) without JavaScript enabled.
Otherwise insert, change and remove ARIA via scripting. For instance, a collapsed section of a tree widget might look like this:
<li role=treeitem aria-expanded=false ...
When the user opens the section, it is changed to this using JavaScript :
<li role=treeitem aria-expanded=true ...
2.8 ARIA validation๐
The easiest method is to use the HTML5 DOCTYPE with ARIA markup and validate using the W3C Nu Markup Checker. ARIA works equally well with any other DOCTYPE
, but validation tools will produce errors when they encounter ARIA markup as the associated DTDs have not been updated to recognise ARIA markup and it is unlikely they ever will be.
These validation errors in versions of HTML prior of HTML5 are in no way indicative of ARIA creating any real world accessibility problems nor do they mean there will be a negative user experience. They are merely the result of old automated validation tests that do not accommodate ARIA accessibility annotations.
Note: The W3C Nu Markup Checker support for ARIA checking is a work in progress, so cannot be wholly relied upon (though it is pretty darn good!) to provide the correct results. It is recommended that if you encounter a result that conflicts with the ARIA conformance requirements in the ARIA specification or the HTML specification, please raise an issue.
2.9 Use of role=presentation or role=none๐
role=presentation
, or its synonym role=none
, removes the semantics from the element it is on.
For example, this code in the HTML tree:
<h1 role="presentation">text</h1>
Becomes this in the accessibility tree:
In other words, it is just reported in the accessibility tree as a text string with no semantic meaning.
For elements with no required children, any elements nested inside the element with role=presentation/none
preserve their semantics.
For example, this code in the HTML tree:
<h1 role="presentation"><abbr>API</abbr></h1>
Becomes this in the accessibility tree:
For elements with required children (such as ul
or table
) any required child elements nested inside the element with role=presentation/none
also have their semantics removed.
For example, this code in the HTML tree:
<table role="presentation">
<tr>
<td>
<abbr>API</abbr>
</td>
</tr>
</table>
Becomes this in the accessibility tree:
Note: Any elements that are not required children of the element with a role=presentation/none
keep their semantics. This includes other elements with required children such as nested lists or nested tables.
For example this code, consisting of a table with another table nested inside it, in the HTML tree:
<table>
<tr>
<td>
<table>
<tr>
<td>
<abbr>API</abbr>
</td>
</tr>
</table>
</td>
</tr>
</table>
Becomes this in the accessibility tree:
By adding role=presentation/none
to the outer table
element, this code in the HTML tree:
<table role="presentation">
<tr>
<td>
<table>
<tr>
<td>
<abbr>API</abbr>
</td>
</tr>
</table>
</td>
</tr>
</table>
Becomes this in the accessibility tree, the semantics of the outer table
including its required children (the tr
and td
elements) are removed by the addition of role=presentation/none
:
Examples of role=presentation/none
use๐
Use in fixing an incorrect table structure
<div aria-readonly="true" role="grid">
<table role="presentation">
<tbody><tr role="row">
<th role="columnheader">Dog Names</th>
<th role="columnheader">Cat Names</th>
<th role="columnheader">Cow names</th>
</tr>
</tbody></table>
<table role="none">
<tbody><tr role="row">
<td role="gridcell">Fido</td>
<td role="gridcell">Whiskers</td>
<td role="gridcell">Clarabella</td>
</tr>
<tr role="row">
<td role="gridcell">Woofie</td>
<td role="gridcell">Claws</td>
<td role="gridcell">Glenn</td>
</tr>
</tbody></table>
</div>
2.10 Practical Support: aria-label, aria-labelledby and aria-describedby๐
Currently aria-label
, aria-labelledby
and aria-describedby
are most robustly supported for associating text content to a subset of interactive content elements, elements that have explicit ARIA widget role value assigned, and for elements that have an explicit landmark role value assigned or those that have implicit ARIA landmark semantics (e.g. <div role="main">
or <main>
). They do not work consistently on links , support on embedded content and grouping content is inconsistent across browsers, assistive technology and operating systems, but they can be safely used on HTML5 form controls including the many input
types and the <aside>
, <footer>
, <article>
, <header>
, <nav>
, <section>
and <main>
elements.
In Internet Explorer, if you use aria-labelledby
with multiple id
references or aria-describedby
with single or multiple id
references, the referenced elements must be what Microsoft terms as accessible HTML elements.
The following example of aria-labelledby
with multiple references uses a span
with a tabindex=-1
added. Refer to Making Non accessible Elements Accessible.
<label id="l1" for="f3">label text</label>
<input type="text" id="f3" aria-labelledby="l1 l2">
<p>other content</p>
<span tabindex="-1" id="l2">more label text</span>
Elements also become accessible HTML elements in Internet Explorer when the element has an ARIA role. For example:
<div aria-describedby="test">text</div>
<div id="test" role="tooltip">tooltip text</div>
2.10.1 Hiding content has no effect on accessible name or description calculation๐
By design, hiding the content (using CSS display:none
or visibility:hidden
or the HTML hidden attribute) of the element(s) referenced by aria-labelledby and aria-describedby does not stop the content from being used to provide the name/description.
By default, assistive technologies do not relay hidden information, but an author can explicitly override that and include hidden text as part of the accessible name or accessible description by usingaria-labelledby
oraria-describedby
.
In the following example the description will be available to assistive technology users in both states:
Non error state: message viusally hidden
<label>Name <input type="text" aria-describedby="error-message"></label>
<span id="error-message" style="display:none">
You have provided an incorrect name</span>
Note: addition of aria-hidden=true
to the referenced element makes no difference:
<span id="error-message" style="display:none" aria-hidden="true">
You have provided an incorrect name</span>
Error state: message visible
<span id="error-message" style="display:inline">
You have provided an incorrect name</span>
Methods to provide context sensitive name/description text๐
If you want to associate context sensitive text, such as an error message you can:- Add the referenced element to the DOM when the error state occurs.
- Add the error text as child of the referenced element in the DOM when the error state occurs.
- Add the id reference in the DOM to the
aria-labelledby/aria-describedby
attribute, when the error state occurs.
2.11 Using ARIA role=application๐
How does role="application" affect a screen reader?๐
On many popular screen readers today, most keystrokes are captured by the screen reader and not the web page when the user is in browse mode. This is necessary for efficient navigation of a page. As of this writing, when application mode is set, many screen reader stop intercepting keystrokes, and pass all keystrokes directly to the browser. Then the user won't be able to navigate the page as easily. For instance they won't be able to skip around the page by headings or read a paragraph of static text line-by-line. However, several screen readers do not behave differently when there is an application role set.
So when should I use it, and when not? ๐
In determining when to use role=application
, one should consider, among other things, the advantages of screen reader keyboard shortcuts weighed against the loss of those features. It generally should not be used, and if it is, usability testing with screen reader users should be conducted.
You do not use role="application"
if a set of controls only contains these widgets, that are all part of standard HTML. This also applies if you mark them up and create an interaction model using WAI-ARIA roles instead of standard HTML widgets:
NOTE: It's not recommended that authors develop custom text input widgets. It's almost always best to use the native inputs for these.
text box
. This also applies to password, search, tel and other newer input type derivativestextarea
check box
button
radio button
(usually inside a fieldset/legend element wrapper)select + option
(s)links
,paragraphs
,headings
, and other elements that are classic/native to documents on the Web.
You also do not use the application
role if your widget is one of the following more dynamic and non-native widgets. Screen readers and other assistive technologies that support WAI-ARIA will support switching between browse and focus modes for these by default too:
tree view
slider
table
that has focusable items and is being navigated via the arrow keys, for example, a list of e-mail messages where you provide specific information. Other examples are interactive grids, tree grids, etc.- A list of tabs (
tab, tablist
) where the user selects tabs via the left and right arrow keys. Remember that you have to implement the keyboard navigation model for this! dialog
andalertdialog
. These causes some screen readers to go into a sort of application mode (implicitly) once focus moves to a control inside them. Note that for these to work best, set thearia-describedby
attribute of the element whose role isdialog
to theid
of the text that explains the dialog's purpose, and set focus to the first interactive control when you open it:
<div role="dialog" aria-label="login" aria-describedby="log1"> <div id="log1" tabindex="-1">Provide user name and password to login.</div> ... ... </div>
toolbar
andtoolbar buttons
,menus
andmenu items
, and similar.
You only want to use role=application
if the content youโre providing consists of only
focusable, interactive controls, and of those, mostly advanced widgets that emulate a real desktop application. Note that, despite many things now being called a web application, most of the content these web applications work with are still document-based information, be it Facebook posts and comments, blogs, Twitter feeds, or even accordions that show and hide certain types of information dynamically. We primarily still deal with documents on the web, even though they may have a desktop-ish feel to them on the surface.
It is not necessary to use role=application
to have control-specific keyboard shortcuts while the user is in forms (focus) mode on their screen reader. For instance, a custom control with ARIA role=listbox
can easily capture all keys pressed including arrow keys, while the user is interacting with it.
In short: The times when you actually will use role=application
will probably be very rare!
So where do I put role=application
in the rare cases it is useful?๐
Put it on the closest containing element of your widget, for example, the parent div
of your element that is your outer most widget element. If that outer div
wraps only widgets that need the application interaction model, this will make sure focus mode is switched off once the user tabs out of this widget.
Only put it on the body element if your page consists solely of a widget or set of widgets that all need the focus mode to be turned on. If you have a majority of these widgets, but also have something you want the user to browse, use role=document
on the outer-most element of this document-ish part of the page. It is the counterpart to role=application
and will allow you to tell the screen reader to use browse mode for this part. Also make this element tabbable by setting a tabindex=0
on it so the user has a chance to reach it.
As a rule of thumb: If your page consists of over 90 or even 95 percent of widgets, role=application
may be appropriate. Even then, find someone knowledgeable who can actually test two versions of this: One with and one without role=application
set to see which model works best.
NEVER put role=application
on a widely containing element such as body
if your page consists mostly of traditional widgets or page elements such as links that the user does not have to interact with in focus mode. This will cause huge headaches for any assistive technology user trying to use your site/application.
For further information on the use of role=application
refer to If you use the WAI-ARIA role "application", please do so wisely!
2.12 Custom Control Accessible Development Checklist:๐
Check your custom control against the following design considerations. If the answer to any of them is 'No' then consider fixing before release or at least documenting the issues to inform other developers that your custom control will not be usable by some people due to limited accessibility support.
design consideration | description | Yes/No |
---|---|---|
focusable | Can you get to the control via the keyboard? Refer to Providing Keyboard Focus | |
keyboard operable | Can you use the control with the keyboard? Refer to Keyboard Navigation | |
touch operable | Can you use the control with touch gestures? With assistive technology enabled? | |
expected operation | Can you operate the control using the standard keys (Refer to ARIA Widget Design Patterns) and/or touch gestures for the control type? | |
clear indication of focus | Can you easily see it when the control has focus? Refer to Visible Focus (WCAG2) | |
label | The control has a text label that is exposed as an accessible name in accessibility APIs | |
role | The control has an appropriate role exposed in accessibility APIs | |
states and properties | The control has any UI states and properties that it has exposed in accessibility APIs | |
color contrast | The control label/description/icon is perceivable/usable for low vision users (Use a color contrast checker.) | |
high contrast mode | The control is perceivable/usable when High Contrast Mode is enabled (e.g. Windows HC mode) |
2.13 ARIA adds nothing to default semantics of most HTML elements๐
In some cases the semantics of a HTML element can be expressed by an ARIA role, state or property. This is known as the element's 'Default Implicit ARIA semantics'
In the majority of cases setting an ARIArole
and/oraria-*
attribute that matches the default implicit ARIA semantics is unnecessary and not recommended as these properties are already set by the browser.
2.13.1 Some examples of redundant ARIA๐
Adding default implicit roles to interactive elements listed in the HTML5 Recommendation is a waste of time:
<button role="button">press me</button>
Adding ARIA state or property attributes in addition to their native HTML counterparts is a waste of time:
<input type="text" required aria-required="true">
<div hidden aria-hidden="true">
Adding ARIA roles and states or properties to long-implemented structural elements is a waste of time:
<h1 role="heading" aria-level="1">heading text</h1>
2.14 Aria roles and properties not available as features in HTML๐
Below are listed the ARIA roles and properties. not considered to be available natively in HTML. It is clear that many roles and properties provided by ARIA, which can be used to convey information to users, are not available in HTML.2.14.1 ARIA Roles๐
2.14.2 ARIA States and Properties (aria-* attributes)๐
aria-activedescendant
aria-atomic
aria-busy
(state)aria-controls
aria-describedby
aria-dropeffect
aria-expanded
(state)aria-flowto
aria-grabbed
(state)aria-haspopup
aria-hidden
(state)aria-label
aria-labelledby
aria-level
aria-live
aria-orientation
aria-owns
aria-posinset
aria-pressed
(state)aria-relevant
aria-setsize
aria-sort
2.15 ARIA Design Patterns and touch device support๐
The ARIA Design Patterns in WAI-ARIA Authoring Practices 1.1 describe how to implement custom UI elements so that they are usable by keyboard only users and understandable to users of assistive technology. Some of the ARIA design patterns currently specify, and rely on, keyboard-specific event handling. This is not supported on devices which only provide a touch screen, and has limited or no support (depending on the specific operating system) on mobile phones/tablets with an additional physical keyboard. An in progress ARIA design patterns - touch UA/AT gap analysis (Google sheet) is available (Also available as a static file in .ods format). Related WAI-ARIA Authoring Practices 1.1 issue
2.16 Recommendations Table:๐
Refer to the Document conformance requirements for use of ARIA attributes in HTML table in the ARIA in HTML specification.
2.17 ARIA Role, State, and Property Quick Reference
Refer to the Allowed ARIA roles, states and properties table in the ARIA in HTML specification.