Have you ever heard about ARIA? It might sound weird and maybe even intimidating at first.
In this post, I'd like to talk about the 5 essential rules of ARIA.
What does ARIA stand for?
Let's start first from the meaning of this acronym.
ARIA - stands for Accessible Rich Internet Applications.
It's a set of roles and attributes that define ways to make web content and web applications (especially those developed with JavaScript) more accessible to everyone.
There are 5 essential rules of ARIA.
First Rule - Don't use ARIA (unless you don't have a choice)
It might sound a bit counter-intuitive, but rather than creating our own custom elements and trying to make them accessible by adding ARIA attributes, we should use native HTML elements instead.
Instead of creating a button using <div>
<div role=“button” tabindex=“0” aria-pressed=“false”>Open</button>
It'd be much better to use native HTML <button>
instead
<button type=“button”>Open</button>
If we can use a native HTML element, then we should do so. We should reach out to ARIA as a last resort.
Second Rule - Prefer native semantics over ARIA
We should always prefer native HTML elements over custom elements with ARIA attributes.
Let's say, we'd like to create a title. In such case, it'd be better if we use a native <h2>
HTML element rather than a <div>
with ARIA attributes.
Not a good idea.
<div role="heading" aria-level="2">Title text</div>
We should prefer to use native HTML elements instead.
<h2>Title text</h2>
NOTE:
If we create an interactive element, let's say a <button>
, using <div>
.
In addition to using proper ARIA attributes, we will need to add appropriate interaction behavior (e.g. click handler) using JavaScript.
That's why, in the case of a <button>
, it is much better and easier to just use a native element.
<button type=“button”>Open</button>
Third Rule - All interactive elements must be usable with a keyboard
All interactive elements, whether it be a custom element we created or a native HTML element, must be usable with both a mouse and a keyboard.
If we created a widget that can be clicked, tapped, dragged, slid, or scrolled. A user should be able to use it with both a mouse and a keyboard.
If using role=button
, on a custom element, 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) and the space
key.
Fourth Rule - Do not use role="presentation"
or aria-hidden="true"
on a focusable element
Using role="presentation"
or aria-hidden
on a focusable element might result in some users focusing on it and getting inaccurate information. In some cases, users won't even be able to discover such elements.
Using either of these on a focusable element might result in some users focusing on 'nothing'.
<button role=“presentation”>press me</button>
<button aria-hidden=“true”>press me</button>
NOTE: Setting aria-hidden
on a parent/ancestor element, of a visible interactive element (e.g. <button>
), will also hide an element from assistive technologies (e.g. screen reader).
<div aria-hidden="true">
<button>press me</button>
</div>
NOTE: We can use aria-hidden
on an element, as long as it's not focusable.
We can set tabindex="-1"
on a focusable element that will remove it from the tab order, so it won't be focusable by a keyboard, but we can still be able to focus it using JavaScript if we want to.
// tabindex="-1" removes the button from the tab order
<button tabindex=“-1” aria-hidden=“true”>press me</button>
NOTE: If we use display: none
or visibility: hidden
(either on an element or on the element's ancestor) it won't be focusable and will be removed from the accessibility tree.
That is, screen readers won't be able to discover it. In such case, we don't need to add aria-hidden
or negative tabindex on such an element.
CSS
.hidden-btn {display: none;}
HTML
<button class=“hidden-btn“>press me</button>
Fifth Rule - All interactive elements must have an accessible name
Accessible name, is a name of a UI element. Each platform has its own accessibility API which provides such property. The value of the accessible name may be derived from a visible or invisible property on an element.
Visible property - visible text of an element. Let's say, a visible text on a button.
Invisible property - ARIA attributes such as aria-label
or aria-labelledby
Let's take a look at a few examples, so we can understand it better.
Here the text "press me" is the visible text of the <button>
and as such, can be used as an accessible name.
<button>press me</button>
When the <button>
receives focus, a screen reader may announce something like "press me, button" concatenating a role (button) of the element and its name (press me).
The order of concatenation and a role description depends on a platform's accessibility API and the assistive technology (e.g. screen reader) that is used.
The <input>
in the code examples below has a visible label "username" , but no accessible name
username <input type="text">
or
<span>username</span> <input type="text">
Here the <input>
has a visible label but it can not be used as an accessible name. It cannot be associated with the <input>
.
In such case, a screen reader won't be able to announce the accessible name of the <input>
. That would be, an accessibility violation.
In comparison, this <input>
has both a visible label and an accessible name.
Using <for>
attribute
<label for="userNameId">username</label>
<input type="text" id="userNameId">
or
Wrapping it with a <label>
<label>
username
<input type="text">
</label>
In the examples above, we use a <label>
element to provide an accessible name for our <input>
.
What if we can't use <label>
or for
attribute?
In such a case we might use ARIA attributes,
namely aria-label
or aria-labelledby
.
Using aria-label
<input type="text" aria-label="Username">
Using aria-labelledby
<span id="fldUsrnm">username</span>
<input type="text" aria-labelledby="fldUsrnm">
In this situation, we use ARIA as a last resort, which is perfectly fine.
Conclusion
There you have it the 5 rules of ARIA
Don't use ARIA (unless you really have to)
Prefer native semantics over ARIA
All interactive elements must be usable with a keyboard
Do not use role="presentation" or aria-hidden="true" on a
focusable elementAll interactive elements must have an accessible name
Of course it's not all, and we barely scratched the surface. Nevertheless, I hope it's a beginning of a better understanding ARIA.
I hope this post was useful for you as a reference.
Top comments (12)
Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍
Thank you. I'll try.
Such precious information. Thank you !
Beautiful post, one of the best for this topic, which is really hard to digest.
Thank you for these words.
I really tried to make it succinct and understandable as much as possible.
What resources do you use to make your HTML more accessible?
MSN? Or is there another resource that is good?
I find it really hard to find what each aria means
Thank you @lukeecart for your question.
I mostly use the official documentation by W3C or MDN.
I do agree, though, that it's not easy to find the needed information, when one's trying to write HTML in a more accessible way.
For the most part, this is the reason why I had decided to write an article in the first place.
Which tools can I use in my next project which will be the best
Not sure what you mean by "tools".
Could you possibly elaborate a bit more?
For A11y testing, you can use Chrome dev tools Audits
Axe (dev tools extension)
or Accessibility Insights for Web (browser extension)
As for writing accessible HTML, most of the time just prefer using native HTML elements (e.g.
<button>
,<ul>
, etc...) over custom ones and follow the 5 ARIA rules.That should be enough for most of the cases.
I want to say for back-end and database
Chrome lighthouse would be a good start. use it with combination of Wave extension
Thank you so much 🧡