Blog

What is ARIA and When Should I Use It? Developer Guide

TestParty
TestParty
September 24, 2025

ARIA is one of the most misunderstood aspects of web accessibility. I've seen developers add ARIA attributes everywhere, thinking they're improving accessibility, when they're actually making things worse. I've also seen developers avoid ARIA entirely, missing cases where it genuinely helps.

Understanding when ARIA is appropriate—and when it isn't—is essential for building genuinely accessible web applications. This guide explains what ARIA does, when you should use it, and common mistakes to avoid.

Q: What is ARIA and when should I use it?

A: ARIA (Accessible Rich Internet Applications) is a set of HTML attributes that communicate accessibility information to assistive technology. Use ARIA when native HTML elements can't express the semantics you need—primarily for custom interactive widgets, dynamic content updates, and complex web applications. The first rule of ARIA: don't use ARIA if native HTML can do the job.

Understanding ARIA

What ARIA Does

ARIA attributes add accessibility semantics to HTML elements. They tell assistive technologies what elements are, what state they're in, and how they relate to other elements.

ARIA provides three types of information:

Roles: What something is (button, tab, menu, dialog) States: Current condition (expanded, checked, disabled) Properties: Static characteristics (label, description, relationship to other elements)

When a screen reader encounters an element, it announces based on these attributes:

<div role="button" aria-pressed="true">
  Toggle Feature
</div>

Screen reader announces: "Toggle Feature, toggle button, pressed"

Why ARIA Exists

HTML was designed for documents, not applications. Native HTML has elements for paragraphs, headings, links, and forms—but no native elements for tabs, trees, carousels, or many modern UI patterns.

ARIA fills this gap, letting developers communicate complex widget semantics that HTML alone can't express.

The First Rule of ARIA

The W3C's first rule of ARIA use:

"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."

-

Why this rule exists:

Native HTML elements have built-in:

  • Keyboard behavior (buttons respond to Enter/Space)
  • Focus management
  • Browser-consistent behavior
  • No JavaScript required

ARIA provides semantics only—not behavior. A div with role="button" isn't automatically keyboard-operable; you must add that yourself.

<!-- Good: native button with full accessibility built in -->
<button>Submit</button>

<!-- Worse: custom button requiring additional work -->
<div role="button" tabindex="0" onclick="..." onkeydown="...">Submit</div>

ARIA Roles

What Roles Do

Roles define what an element is. They override the element's native semantics for assistive technology.

<!-- This is announced as a button, not a link -->
<a href="#" role="button">Click me</a>

Categories of Roles

Landmark roles: Define page regions

  • banner (header)
  • navigation
  • main
  • complementary (aside)
  • contentinfo (footer)
  • search

Widget roles: Interactive components

  • button, link, checkbox, radio
  • tab, tablist, tabpanel
  • menu, menuitem, menubar
  • dialog, alertdialog
  • slider, spinbutton
  • tree, treeitem
  • listbox, option

Document structure roles: Content organization

  • article, document, region
  • heading (with aria-level)
  • list, listitem
  • table, row, cell, columnheader, rowheader

Live region roles: Dynamic content

  • alert
  • status
  • log
  • marquee
  • timer

When Landmark Roles Are Needed

HTML5 introduced semantic elements that map to landmark roles:

| HTML Element | Implicit ARIA Role             |
|--------------|--------------------------------|
| `<header>`   | `banner` (when top-level)      |
| `<nav>`      | `navigation`                   |
| `<main>`     | `main`                         |
| `<aside>`    | `complementary`                |
| `<footer>`   | `contentinfo` (when top-level) |
| `<form>`     | `form` (when named)            |
| `<section>`  | `region` (when named)          |

Use semantic HTML elements instead of divs with roles:

<!-- Better: semantic HTML -->
<nav>...</nav>

<!-- Worse: div with role -->
<div role="navigation">...</div>

ARIA States and Properties

States: Dynamic Conditions

States indicate current condition and typically change during interaction:

aria-expanded: Whether an expandable section is open

<button aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu" hidden>...</ul>

aria-selected: Whether an option is selected

<li role="option" aria-selected="true">Option 1</li>

aria-checked: Checkbox or toggle state

<div role="checkbox" aria-checked="true">...</div>

aria-pressed: Toggle button state

<button aria-pressed="true">Bold</button>

aria-disabled: Whether element is disabled

<button aria-disabled="true">Submit</button>

aria-hidden: Remove from accessibility tree

<div aria-hidden="true">Decorative content</div>

Properties: Static Characteristics

Properties provide additional information that doesn't typically change:

aria-label: Accessible name when visible text isn't available

<button aria-label="Close dialog">Ă—</button>

aria-labelledby: Reference another element as label

<h2 id="section-title">Settings</h2>
<div role="region" aria-labelledby="section-title">...</div>

aria-describedby: Reference additional description

<input type="password" aria-describedby="password-hint">
<p id="password-hint">Must be at least 8 characters</p>

aria-controls: Element this one controls

<button aria-controls="panel" aria-expanded="false">Toggle</button>
<div id="panel">...</div>

aria-live: Announce dynamic content updates

<div aria-live="polite">Status updates appear here</div>

aria-required: Form field is required

<input type="text" aria-required="true">

When to Use ARIA

Use Case 1: Custom Interactive Widgets

When you build custom components that HTML doesn't provide natively:

Tabs:

<div role="tablist">
  <button role="tab" aria-selected="true" aria-controls="panel1">Tab 1</button>
  <button role="tab" aria-selected="false" aria-controls="panel2">Tab 2</button>
</div>
<div role="tabpanel" id="panel1">Content 1</div>
<div role="tabpanel" id="panel2" hidden>Content 2</div>

Tree view, combobox, carousel, and other patterns need ARIA because HTML doesn't have native equivalents.

The WAI-ARIA Authoring Practices Guide documents correct patterns for these widgets.

Use Case 2: Dynamic Content Updates

When content changes without page reload, screen readers need notification:

<!-- Alert for important messages -->
<div role="alert">Form submitted successfully!</div>

<!-- Status for less urgent updates -->
<div role="status" aria-live="polite">3 items in cart</div>

<!-- Live region for ongoing updates -->
<div aria-live="polite" aria-atomic="true">
  Search results: 24 found
</div>

Use Case 3: Missing Visible Labels

When visible text label isn't practical:

<!-- Icon-only button -->
<button aria-label="Close">
  <svg><!-- X icon --></svg>
</button>

<!-- Search input with implicit label -->
<input type="search" aria-label="Search products">
<button>Search</button>

Use Case 4: Supplementing Relationships

When relationships between elements need explicit connection:

<!-- Error message association -->
<input type="email" aria-describedby="email-error" aria-invalid="true">
<p id="email-error">Please enter a valid email</p>

<!-- Form group labeling -->
<div role="group" aria-labelledby="shipping-label">
  <h3 id="shipping-label">Shipping Address</h3>
  <!-- form fields -->
</div>

Use Case 5: Hiding Decorative Content

Remove purely decorative content from accessibility tree:

<!-- Decorative icon -->
<span aria-hidden="true">🎉</span>

<!-- Decorative image -->
<img src="decoration.svg" alt="" aria-hidden="true">

When NOT to Use ARIA

Don't Use ARIA for Native HTML Capabilities

<!-- Wrong: ARIA on elements that don't need it -->
<button role="button">Submit</button>
<a role="link" href="/page">Link</a>
<h2 role="heading" aria-level="2">Title</h2>

<!-- Right: native elements already have these semantics -->
<button>Submit</button>
<a href="/page">Link</a>
<h2>Title</h2>

Don't Use ARIA to Fix Broken HTML

<!-- Wrong: ARIA can't make non-semantic markup accessible -->
<span role="heading" aria-level="1">Page Title</span>
<div role="button" onclick="...">Click me</div>

<!-- Right: use proper HTML -->
<h1>Page Title</h1>
<button onclick="...">Click me</button>

Don't Add ARIA Without Implementing Behavior

<!-- Dangerous: looks like tabs to screen reader, but won't work like tabs -->
<div role="tablist">
  <div role="tab">Tab 1</div>
  <div role="tab">Tab 2</div>
</div>

ARIA doesn't add keyboard navigation, focus management, or any behavior—only semantics.

Common ARIA Mistakes

Mistake 1: Redundant ARIA

<!-- Redundant: button already has button role -->
<button role="button">Submit</button>

<!-- Redundant: img already supports alt -->
<img src="photo.jpg" alt="Team photo" aria-label="Team photo">

Mistake 2: Invalid ARIA

<!-- Invalid: aria-label on non-interactive element -->
<p aria-label="Important paragraph">Content</p>

<!-- Invalid: wrong role for element type -->
<a href="/page" role="button">Navigate</a>

Mistake 3: ARIA Without Full Implementation

Adding widget roles without implementing required keyboard patterns, state management, and focus handling.

Mistake 4: Hiding Important Content

<!-- Dangerous: removes content from screen readers -->
<main aria-hidden="true">Actual page content</main>

Mistake 5: Overusing aria-hidden

<!-- Wrong: hiding content that should be accessible -->
<button>
  <span aria-hidden="true">Submit</span>
</button>
<!-- Screen reader: "button" with no name -->

Testing ARIA Implementation

Verify with Screen Readers

Screen reader testing reveals whether ARIA is implemented correctly:

  • Are roles announced appropriately?
  • Are states (expanded, selected) announced when they change?
  • Do widgets behave as expected?

Use Browser DevTools

Chrome and Firefox DevTools show computed accessibility properties:

  • Open DevTools → Elements → Accessibility pane
  • See computed role, name, state
  • Verify ARIA is having intended effect

Automated Checking

Automated tools catch many ARIA errors:

  • Invalid attribute values
  • Missing required attributes
  • Prohibited attribute combinations

TestParty identifies ARIA issues alongside other accessibility problems.

FAQ Section

Q: Does ARIA make elements keyboard accessible?

A: No. ARIA only provides semantics—information about what elements are. It doesn't add behavior. A div with role="button" still needs JavaScript for keyboard handling (Enter/Space activation) and tabindex="0" to be focusable.

Q: Should I add ARIA to all my HTML elements?

A: No—most elements don't need ARIA. Native HTML elements already have implicit roles and semantics. Adding ARIA unnecessarily creates maintenance burden and risks introducing errors. Use ARIA only when native HTML can't express needed semantics.

Q: What's the difference between aria-label and aria-labelledby?

A: aria-label provides text directly: aria-label="Close dialog". aria-labelledby references another element's ID that contains the label text: aria-labelledby="dialog-title". Use aria-labelledby when visible text exists; use aria-label when no visible text is appropriate.

Q: Can ARIA fix accessibility problems in third-party code?

A: Sometimes. Adding ARIA attributes to wrapper elements can help in some cases. However, fundamental accessibility issues in third-party code (missing keyboard support, wrong element types) often can't be fixed with ARIA alone.

Q: Where can I learn correct ARIA patterns?

A: The WAI-ARIA Authoring Practices Guide documents correct patterns for common widgets with code examples and keyboard expectations. It's the authoritative reference for implementing ARIA correctly.

ARIA Done Right

ARIA is a powerful tool when used appropriately:

  • Use native HTML first
  • Add ARIA only when HTML can't express needed semantics
  • Implement full keyboard behavior alongside ARIA semantics
  • Test with actual screen readers
  • Refer to WAI-ARIA Authoring Practices Guide for patterns

ARIA doesn't make things accessible automatically—it communicates accessibility information that assistive technology can use. The behavior, keyboard access, and focus management are still your responsibility.

Ready to identify ARIA issues and other accessibility problems? Get a free accessibility scan to find problems before your users do.


Related Articles:


Here's the deal—we use AI to help create content (it's 2025, after all), but humans on our team review everything. TestParty does Shopify accessibility and WCAG testing, and we love talking shop. For legal stuff though, please consult actual experts.

Stay informed

Accessibility insights delivered
straight to your inbox.

Contact Us

Automate the software work for accessibility compliance, end-to-end.

Empowering businesses with seamless digital accessibility solutions—simple, inclusive, effective.

Book a Demo