ARIA Attributes

ARIA attributes are a set of roles and attributes that define ways to make the web more accessible to people with disabilities. Note that ARIA does not add functionality!

There is a saying "No ARIA is better than bad ARIA." In WebAim's survey of over one million home pages, they found that Home pages with ARIA present averaged 41% more detected errors than those without ARIA. While ARIA is designed to make web pages more accessible, if used incorrectly, it can do more harm than good. -- Gerard K. Cohen[1]

ARIA Support

ARIA support varies from browser to browser and from each assistive device to another. You can't query for if an ARIA role or attribute is supported (and often, ARIA standards are not specified for certain technologies), so the only thing you can do is test, test, test. This is another reason why no ARIA is usually better than bad ARIA.

The 5 Rules of ARIA[6]

  1. Don't use ARIA (if you can use HTML instead)
  2. Don't change native semantics. The ARIA role will take precedence over the HTML, so don't mess with it.
  3. All interactive ARIA roles need to be operable by keyboard. If it is operated by mouse, it must also be operated by keyboard.
  4. Don't use role="presentation" or aria-hidden="true" on visible focusable elements.
  5. All interactive elements must have an accessible name.

Semantic HTML

Developers should prefer using the correct semantic HTML element over using ARIA, if such an element exists. For instance, native elements have built-in keyboard accessibility, roles and states. However, if you choose to use ARIA, you are responsible for mimicking the equivalent browser behavior in script.[1]

Here are some examples of bad ARIA usage:

<div role="banner"></div>
<div role="complementary"></div>
<div role="form"></div>
<div role="main"></div>
<div role="navigation"></div>
<div role="region"></div>
<div role="contentinfo"></div>
<div role="search"></div>

Here are those examples being used with good semantic HTML:

<!-- A section tag needs an accessible name to truly replace the "region" role  -->
<div role="search"></div>
<!-- No associated semantic HTML -->

Another example is anchor tags (<a href="#">) are handled differently than buttons (<button>), so adding a role="button" to your a tag will result in unexpected behavior for the user, since they are expecting a button but the interaction is that of an a tag.

At a certain point, HTML alone is not enough. And what I will say is that ARIA should never really be an option, but when it is, it's your only option.[2]

role="presentation" and aria-hidden="true"[9]

The presentation role strips the element of all semantics. So if a user can focus on that element, they will have no guidance on how to handle it or what it is for. For certain elements, this also strips all the semantics of the children (<ul> for example). For others, it does not (<a> or <button> will always be focusable and in the accessibility tree).

The hidden aria attribute does not affect whether or not it is visible, like a display: none; might in CSS. It will still be rendered and visible for the user, so setting hidden won't provide the user with any additional help in understanding the element, nor will it hide it from them.

When you’re thinking about removing an element from the accessibility tree first think, “Am I removing the element all together or just the semantics?”[9]

Accessible Names

Adding accessible names will help give users of assistive devices context regarding certain elements. For instance, if there is a bare <input />, the user will just be told there is an input. But with an accessible name, the user can be told what the input is for, what it relates to, etc.

Certain HTML elements provide these accessible names natively. For instance, the <input /> example is best served by using an associated <label> with the proper attributes.

While having a one-to-one programmatic label that is native to HTML is ideal, there are other methods.


aria-labelledby references the ID of another DOM element, whose text content will be read to the user. This attribute also has the advantage of allowing that text content to be translatable by Google Translate and other services, and the ability to chain multiple IDs to compose a more complex label (e.g. aria-labelledby="first-name last-name").


The value of the aria-label attribute will be read out as is and does not have the advantages of aria-labelledby.

Accessible Roles[4]

ARIA roles are the way you provide semantics to HTML elements, and ultimately how an assistive device user will know what something is. They are a contract between you and the user. But while they are a contract, they do not provide interaction or functionality; they just tell the user what they can expect from a given element, and you must provide the functionality.

You cannot make your own roles. You must use the ones in the ARIA standard.

Role Types


Widget roles are meant to indicate interactive elements. Interactive elements all require three different attributes: name, role, and value. This is because dynamic visual changes must be presented programmatically.

There are two types of widget roles: standalone and composite roles.

Standalone widgets exist on their own or as part of a composite. You can see the list of standalone widgets on the ARIA roles standard page[4], and they include checkbox and link.

Composite widgets are parent roles or containers for standalone widget roles. These have a very specific standard to adhere to. The relationships between parent and child roles are very specific and must be done a particular way. Some roles can only be used as a child to a specific composite role.

Document Structure

These are mostly non-interactive, but provide context like heading, image, list, and table. Semantic HTML is often provided to handle this.

Live Region

Live region roles are pieces of content that are updated dynamically and announced by assistive technology. These don't need to be actively focused by a user in order to be announced. Some examples are chat logs, sports scores, and timers.

Certain elements are naturally live regions[11], like those with the alert role. Any element can be a live region by adding the aria-live[10] attribute and setting it to either polite or assertive. polite should always be used unless it is absolutely necessary that the user is interrupted to hear whatever is in the live region. This is very rare.

Some other attributes that are useful for customizing the behavior of live regions are aria-atomic and aria-relevant.


Window roles are in-window pop-ups. They have special meaning in document structure, and so are not considered composite roles.

Supported States and Properties[5]

To find what kind of states and properties are allowed for a given role or semantic element, we can check out the definition of the role we are using and have that help inform our decision. For instance, for the button role, there are two supported states and properties: aria-expanded and aria-pressed. Each of these states have their own documentation which will provide the allowed values for their attributes. Then, using Javascript, we can update these values in the markup in real time to help provide the accessibility that a given element requires.

Testing Accessibility

In the browser, there is a separate accessibility tree, similar to the DOM tree, that can be inspected in the devtools. While this is convenient, this is not enough to say that the site is truly accessible, and it must be tested using actual assisted devices.


  2. Gerard K. Cohen's talk on the ARIA Spec for the Uninitiated, and the blog post part 1, part 2, part 3
  3. Official ARIA Standard
  4. ARIA Roles: standard, MDN
  5. Supported States and Properties, and Definition of roles and where you can find appropriate states and properties
  6. % rules of ARIA
  7. WAI-ARIA Authoring Practices
  8. ARIA, Accessibility APIs and coding like you give a damn! – Léonie Watson / Front-Trends 2015
  9. role="presentation" and aria-hidden="true"
  10. aria-live
  11. ARIA live regions

Last modified: 202401040446