ARIA — Accessible Rich Internet Applications — is one of the most powerful and most misused tools in web accessibility. When used correctly, ARIA bridges the gap between complex web interfaces and assistive technologies like screen readers. When used incorrectly, it actively makes things worse. This guide covers when ARIA is truly needed, which attributes matter most, and the mistakes that trip up even experienced developers.

The First Rule of ARIA

The first rule of ARIA use, as stated by the W3C, is: if you can use a native HTML element or attribute with the semantics and behavior you require already built in, do so instead of adding ARIA. Native HTML elements like <button>, <a>, <input>, <select>, <nav>, <main>, and <header> carry built-in semantics and keyboard behavior that ARIA cannot replicate. A <div role="button"> is almost always worse than a <button> because you must manually implement keyboard handling, focus management, and activation behavior that the native element provides for free.

ARIA should be used when native HTML does not provide the semantics you need — for example, when building a tab interface, a tree view, a combobox with autocomplete, or a live region that announces dynamic content changes. These patterns have no native HTML equivalent, so ARIA roles and properties are necessary to communicate the widget's purpose and state to assistive technologies.

Key ARIA Roles

ARIA roles tell assistive technologies what a given element is. Some of the most commonly needed roles include:

  • role="tablist", role="tab", role="tabpanel": Used together to create an accessible tab interface. The tablist contains the tabs, each tab is associated with a tabpanel via aria-controls, and the active tab is indicated with aria-selected="true".
  • role="dialog" and role="alertdialog": Used for modal windows. A dialog requires an accessible name (via aria-labelledby or aria-label) and proper focus management — focus must move into the dialog when it opens and be trapped within it until it closes.
  • role="alert": Creates an assertive live region that is announced immediately by screen readers. Use this for urgent messages like error notifications. Avoid overusing it — if everything is announced as an alert, nothing feels urgent.
  • role="status": Creates a polite live region that is announced when the screen reader finishes its current task. Use this for non-urgent status updates like "3 results found" or "File saved."
  • role="navigation", role="banner", role="main", role="contentinfo": Landmark roles that correspond to HTML5 elements (<nav>, <header>, <main>, <footer>). Use the native elements instead of ARIA roles when possible.

aria-label vs aria-labelledby vs aria-describedby

These three attributes are the most frequently used — and confused — ARIA properties. Understanding the distinction is critical:

  • aria-label: Provides an accessible name as a string directly on the element. Use it when there is no visible text label for the element. For example, an icon-only button needs an aria-label to tell screen readers what it does: <button aria-label="Close">.
  • aria-labelledby: Points to one or more element IDs whose text content serves as the accessible name. Use it when the label text already exists somewhere in the DOM and you want to reuse it. This is preferred over aria-label when visible text is available because it keeps the visual label and the accessible name in sync.
  • aria-describedby: Points to elements that provide a description — additional context beyond the accessible name. For example, a password field might use aria-describedby to link to help text that explains the password requirements. Descriptions are announced after the name and role, and users can typically skip them.

Live Regions

Live regions are one of the most important ARIA features for dynamic web applications. They allow screen readers to announce content that changes without the user navigating to it. This is essential for chat messages, form validation errors, search result counts, progress indicators, and any other dynamic content that updates without a page reload.

There are two politeness levels: aria-live="polite" waits for the screen reader to finish its current announcement before speaking the new content. aria-live="assertive" interrupts whatever the screen reader is currently saying. Use assertive sparingly — it is the equivalent of someone shouting over a conversation. Most updates should be polite. Use assertive only for critical error messages or time-sensitive alerts.

A crucial implementation detail: the live region element must exist in the DOM before the content changes. If you dynamically inject an element with aria-live, and the content is already populated when the element is added, screen readers will not announce it. Create the live region container on page load (it can be empty), and then update its content when you need an announcement.

Common Mistakes

Here are the ARIA mistakes we see most frequently in audits:

  1. Using role="button" on a div instead of using a button element. You lose native keyboard handling (Enter and Space to activate), focus management, and form submission behavior.
  2. Adding aria-label to elements that already have visible text. If the button says "Submit" visually, do not add aria-label="Submit form" — this creates a disconnect between what sighted users see and what screen reader users hear, violating WCAG Success Criterion 2.5.3 Label in Name.
  3. Using aria-hidden="true" on interactive elements. This hides the element from assistive technologies while leaving it visible and focusable, creating a confusing experience where keyboard users can focus an element that screen readers cannot see.
  4. Overusing live regions. When too many live regions fire simultaneously, screen readers become overwhelmed with announcements. Be selective about what gets announced.
  5. Missing required ARIA properties. Many ARIA roles have required properties. A role="checkbox" requires aria-checked. A role="slider" requires aria-valuenow, aria-valuemin, and aria-valuemax. Omitting these properties leaves assistive technologies with incomplete information.

Testing with Screen Readers

The only reliable way to verify your ARIA implementation is to test it with real screen readers. Automated tools can check that ARIA attributes are valid and that required properties are present, but they cannot tell you whether the user experience actually makes sense. Test with VoiceOver on macOS (built in, activate with Command+F5), NVDA on Windows (free, open source), and TalkBack on Android. Navigate your interface using only the screen reader's commands — do not look at the screen while testing. Listen to what is announced. Ask yourself: would I know what this element is, what state it is in, and what will happen when I activate it? If the answer is no, your ARIA needs work.