Skip navigation

ARIA roles, explained.

Published 2021/07/29 14:00

What are ARIA "roles" and how can they make your website more accessible?

Let's explain.

Let's suppose you have a website. On this website you have simple form where your users can subscribe to your newsletter using their email address:

The form is quite simple and straightforward:

  • A label for the email input box
  • The email input box
  • A submit button

For the label you use the <label> tag. For the input box you use <input>. All within a <form> tag:

  <label for="email">Email: </label>
  <input type="text" id="email" id="email"/>

For the button however, for various reasons, instead of using the <button> tag, you decide to create a <span> instead:

  <label for="email">Email: </label>
  <input type="text" id="email" id="email"/>

  <span onclick="submitForm()">Submit</span>

You style the span to look like a button. You add some code which makes it act like a button. But there's a problem:

Semantically, it's not a button. A screen reader, for example, won't be able to know that this actually a button…

…unless you specifically tell it so.

You can turn your span into a semantic button by using an ARIA role attribute.

So to turn our span into a button, we add role="button" as an attribute:

  <label for="email">Email: </label>
  <input type="text" id="email" id="email"/>

-  <span onclick="submitForm()">Submit</span>
+  <span onclick="submitForm()" role="button">Submit</span>

Now the screen reader knows that this acts like a button which is supposed to do something, and it will announce it as such.

But how about keyboard access? Spans aren't focusable by default so we need to include tabindex to our span:

  <label for="email">Email: </label>
  <input type="text" id="email" id="email"/>

-  <span onclick="submitForm()" role="button">Submit</span>
+  <span onclick="submitForm()" role="button" tabindex="0">Submit</span>

That's it. We now have a custom element that looks, acts and is semantically a button.

button is just an example of the many ARIA roles that exist out there.


  • alert: used to signify that this element is dynamically updated.

  • dialog: used to signify that this element is a dialog, usually displayed on top of the rest of the page.

And that's it. Thanks for reading. Which ARIA roles do you frequently use and why? Let me know on Twitter!

Explained (28 part series)

  1. Javascript Scopes, explained.
  2. Javascript Promises, explained.
  3. Accessibility, explained.
  4. React, explained
  5. Should I use forEach() or map()?
  6. Should I use Flexbox or CSS Grid?
  7. Docker, explained.
  8. Unit testing, explained
  9. Git, explained.
  10. Typescript, explained.
  11. async/await, explained.
  12. The DOM, explained.
  13. Regular expressions, explained
  14. GraphQL, explained.
  15. Vue, explained.
  16. Svelte, explained.
  17. API, explained.
  18. Javascript Hosting, explained.
  19. Immediately Invoked Function Expressions (IIFE), explained.
  20. ARIA roles, explained.
  21. Test-driven Development, explained.
  22. ARIA live regions, explained.
  23. aria-label in accessibility, explained.
  24. Type coercion in Javascript, explained.
  25. Variables, explained.
  26. if statements, explained.
  27. Arrays, explained.
  28. Currying in Javascript, explained.
2021 Savvas Stephanides
Buy me a coffee
Some icons from Freepik