Common ARIA mistakes and how to avoid them
So you want to make your website more accessible? Great! And you've heard about ARIA, which stands for Accessible Rich Internet Applications. Just slap some ARIA attributes on all HTML elements and your page is accessible? Wrong!
If you don't know what you're doing, you'll end up making your website even less accessible! There's a reason why the first rule of ARIA is: No ARIA is better than Bad ARIA! Use native HTML elements and attributes with the semantics and behaviour you require.
Photo: © Ketut Subiyanto / pexels.com
Let's take a look at use cases for ARIA and common mistakes you should avoid.
ARIA, what is it good for?
Persons with certain types of disabilities use assistive technologies to interact with web content. For example, blind users navigate websites with the help of screen readers. People with motor disabilities may rely on speech recognition software to interact with a website.
Web developers can use ARIA roles and attributes to convey semantics of the content to users of assistive technologies. You can set aria-expanded on an element to indicate if a control is expanded or collapsed. The aria-selected attribute indicates if, e.g., a tab is currently selected or not.
<h3> <button type="button" aria-expanded="false" aria-controls="section1" id="header1"> Personal Information </button> </h3> <div id="section1" role="region" aria-labelledby="header1"> <!-- Panel content that is shown/hidden via button --> </div>
In general, only use ARIA for custom widgets like, e.g., an expansion panel. Check out the ARIA Authoring Practices Guide, which describes how to apply accessibility semantics to common design patterns and widgets.
Bad ARIA practices
I've audited hundreds of websites for accessibility. One thing I've noticed is: Many web developers apparently have no idea what they're doing! They clutter the DOM with ARIA roles and attributes as if there was no tomorrow. I'll show you some of the most common mistakes I've encountered.
Using aria-hidden="true" on a focusable element
ARIA gives you full control over the accessibility tree, which is a modified version of the DOM that is presented to assistive technolgies. The aria-hidden attribute allows you to remove an element from the accessibility tree and thereby hide it from screen reader users.
<a href="https://www.stuff.com" aria-hidden="true">Interesting Stuff</a>
The problem is: Removing a focusable element like a link from the accessibility tree does not remove it from tab order. A screen reader user tabbing through the website will arrive at the link and hear “empty” or something similar. Please, don't do this!
Setting an aria-label different from the visible label
Imagine you're a university student in Vienna and want to register for a lecture online. Because of your hand-tremor, you use voice recognition software to operate the website. You encounter the following web form in German:
<form action=""> <div class="form-field"> <label for="firstname">Vorname</label> <input type="text" aria-label="First Name" name="firstname" id="firstname"> </div> <div class="form-field"> <label for="lastname">Nachname</label> <input type="text" aria-label="Last Name" name="lastname" id="lastname"> </div> <!-- Other fields --> </form>
To fill out the form, you want to focus on the first input field with the visible label “Vorname”. Therefore, you speak the voice command “Vorname klicken” (in German), but nothing happens. What is going on?
As the code above shows, the label element is programmatically associated with the input field using the for attribute. Unfortunately, the aria-label attribute overwrites the input element's accessible name with “First Name”. This means, that the control's name does not include the visible label.
So the form is not easy to operate for voice recognition users and it also represents a clear WCAG violation. Fun fact: This is an actual example from the German website of a large university in Vienna.
The aria-labelledby attribute references an ID that doesn't exist
You can use the aria-labelledby attribute to label an element by referencing another element. Its value should be a list of one or more ID values referencing the elements that label the current element. Here's an example:
<nav aria-labelledby="sidenav-title"> <h2 id="sidenav-title">Related Content</h2> <ul> <!-- List of links --> </ul> </nav>
If there were no element with the id “sidenav-title”, then the nav element would have no label. This would result in a less than optimal experience for screen reader users. Therefore, always check that the elements referenced by aria-labelledby are present in the DOM.
Navigation Menu with role="menubar" or role="menu"
Many websites include site navigation that is styled to look like a menubar with expandable sections. Because of the visual appearance, a lot of web developers think that they should apply the following semantic roles:
<ul role="menubar"> <li role="none"> <a role="menuitem" href="/">Home</a> </li> <li role="none"> <a role="menuitem" aria-haspopup="true" aria-expanded="false" href="#">About</a> <ul role="menu" aria-label="About"> <li role="none"> <a role="menuitem" href="/overview">Overview</a> </li> <li role="none"> <a role="menuitem" href="/administration">Administration</a> </li> </ul> </li> </ul>
The problem with this markup is the expectations it creates. The roles menubar and menu should be used for menu widgets that offer a list of choices to the user, such as a set of actions. These menus should behave like native operating system menus, which means: They should implement a specific set of keyboard interactions, including navigation with arrow keys.
If you create a site navigation with, e.g., role="menubar", then screen reader users will expect to navigate the menu with the arrow keys. When this doesn't work, they'll be confused. A better alternative is to implement the disclosure pattern for site navigation with expandable groups.
Basic rules for using ARIA
As we've seen, a lot can go wrong with ARIA. Here's a list of basic rules that will make your life easier:
- Go for native HTML elements first.
- Do not change native semantics, unless you really have to.
- Use ARIA for custom widgets and strictly follow the Authoring Practices Guide.
- All interactive ARIA controls must be usable with the keyboard.
- Test your code with assistive technologies like screen readers and voice recognition software.