The rules on using ARIA

In my previous post about the differences between the ARIA labeling variants I mentioned the first rule of ARIA — which is often mentioned as “Don’t use ARIA” — and that I would dive deeper into the five rules of ARIA.

If you never heard of ARIA before, let me give you a short introduction. It’s a set of attributes to enable frontend developers create accessible web apps. Look at it as an add-on, or a layer, on top of HTML. Often it’s not necessary to use ARIA because HTML offers a native solution for us. But sometimes our UI components are so complex that they just don’t fit anywhere in the native HTML options. Then it’s time to bring out ARIA and use it to create an accessible experience for everyone.

But, we should be careful with ARIA, because of its double-edged sword characteristic. When it’s used properly, it greatly improves the user experience. But when it’s used incorrectly — or partially — it could break the user experience. To a point where it's completely unusable.

Enough about the intro, let’s go over the five rules on how to use ARIA!

1. Prefer semantic HTML over ARIA

If you can use a native HTML element or attribute with the semantics and behavior 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 – W3C, First rule of ARIA

We should prefer to use the semantic HTML option, if it's available to us. We shouldn’t opt for ARIA for the sake of using ARIA. Although the intent of ARIA is to make things accessible, it’s not the only option available to us. It’s still the only option when things get complex in the UI. But, we have to remember that ARIA came before HTML 5. And when HTML 5 came, it introduced a lot of semantic elements that we no longer have to reproduce through ARIA.

Let’s elaborate on this further with an example.

Let’s not do this

<div role="button">This is a button</div>

Let’s do this instead

<button>This is a button</button>

What’s the difference between role="button" and <button> in this example? They’re the same semantic wise. Both elements should are buttons. So why should we prefer semantic HTML over ARIA? Well, if we would use the role="button" approach we’re not even halfway of what a semantic <button> would give us.

Let’s take the <div role="button"> example and see what’s missing, step by step. The element has its role, so it's recognised as a button. But we can’t focus this element with a keyboard, because there’s no tabindex attribute present. Which the <button> would have given us, out of the box.

It's not only focus management we're missing. It's also the keyboard functionality for interacting with the button that's missing. For instance, when a button has focus, we should be able to press the Space key to activate the button. To check which other interactions we’re missing out on I recommend to read the design patterns for a button from W3C.

In short, let’s use semantic HTML over ARIA, so that we don't have to do the work! This is the main takeaway that I want to give you.

2. Don’t alter the meaning of a semantic HTML element

Do not change native semantics, unless you really have to. – W3C, Second rule of ARIA

When we use a semantic HTML element its meaning has been implicitly given by the element. In other words, a <button> has the role of a “button”. But, what happens if we’re using that same <button> and we give it the ARIA role="header"? Well, we've explicitly gave it a different meaning. And this could lead to unwanted side effects.

Let’s take an unordered list, <ul>, as an example. Everything we expect from an <ul> are right. For instance, it should have a list of <li>. And if we leave it at that, screen readers will be able to understand it. We enable the screen reader to announce how many list items are present. And it will then proceed to announce each list item one by one.

But, when we add the role="navigation" on the <ul>, it becomes a navigation landmark . The semantics are overridden. and screen readers have lost the ability to do what they could do before. Leaving screen reader users guessing what it means.

3. All interactive elements must be usable by a keyboard

All interactive ARIA controls must be usable with the keyboard. – W3C, Third rule of ARIA

The third rule is somewhat linked to the first rule. Let’s use example from the first rule — the <div role="button"> — to explain how they relate to each other. We’ve learned, in the first rule, that when we use the role attribute that we're not done. That we don't have any keyboard functionality. So again, for this rule it's best to go for the semantic HTML element. Because by doing so, we gain the keyboard functionality out of the box.

But, what if we have a complex UI component — often referred as a custom widget — which needs to be interactive. Well, we first need to determine what our complex UI component should act as. To do that we could visit the design patterns and see how it fits. From there we could check which keyboard interactions are expected. In other words, what do we expect to happen when we press the Space key.

4. Focusable elements shouldn’t be hidden

Do not use role="presentation" or aria-hidden="true" on a focusable element. – W3C, Fourth rule of ARIA

The fourth rule focusses — no pun intended, I swear — on ensuring that focusable elements are present in the Accessibility Tree . Otherwise, they're hidden from assistive technologies (e.g. a screen reader).

The aria-hidden="true"role="presentation" and role="none" attributes may look similar. But their intent is quite different!

The role="presentation" and role="none" attributes are the same. The role="none" attribute is actually an alias for role="presentation".

When the button has the aria-hidden="true" attribute, it’s still present in the HTML DOM. So it's still possible to focus the button with a keyboard. But, when we navigate with the screen reader, it will not know of the button's existence.

We shouldn't use the aria-hidden="true" attribute on any focusable or interactive element. Because it will then be impossible to focus or interact with such elements for a lot of people.

5. All interactive elements require an Accessible Name

All interactive elements must have an accessible name. – W3C, Fifth rule of ARIA

All interactive elements (e.g. an <input>) require an Accessible Name. Otherwise, assistive technologies have no clue what the interactive element means.

Let’s take a plain <input> with a <span> next to it, which acts as the visual label. So no <label>, aria-label or aria-labelledby. What would a screen reader announce, when the user has focus on the input?

<input type="text">

Voice Over on MacOS would say something like: Edit text

The screen reader user is confused and needs to guess what the input means, since they can only hear “Edit text”.

This would impact voice recognition users (e.g. VoiceControl on MacOS) as well. If the Accessible Name is present, then it's possible to interact with the <input> element directly. For example, with the VoiceOver command: “Click [insert accessible name]”. If the Accessible Name isn't available, they need to resort to other means to interact with the element. Which could seriously affect their user experience.

How could we provide the Accessible Name?

There are three separate techniques to provide the Accessible Name:

  1. For <a> and <button> we provide the Accessible Name through the link text/button value we’ve given them
  2. For <input> elements we provide the Accessible Name through either a explicit <label>, aria-label or the aria-labelledby
  3. For anything else (e.g. custom elements, landmarks, etc) we provide the Accessible Name either through aria-label or the aria-labelledby attributes


You’ve made it to the end! That was quite a lot of information on how we should use ARIA. So, let’s summarise all the things we’ve learned: