ARIA Attributes Explained: Roles, States & Properties Guide

ARIA roles and attributes can make complex UIs accessible to screen readers, but misuse makes things worse. Learn when to use ARIA, when to skip it, and the most common mistakes to avoid.


The first rule of ARIA: don't use ARIA

That might sound contradictory for an article about ARIA, but it's the official guidance from the W3C's own documentation. The first rule states: "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."

ARIA (Accessible Rich Internet Applications) is a set of attributes you can add to HTML elements to communicate information to assistive technologies. It bridges the gap between what native HTML can express and what complex web applications need. But ARIA doesn't change how an element actually works - it only changes how it's announced to screen readers.

This distinction is critical. A <div role="button"> will be announced as a button, but it won't be focusable with Tab, won't respond to Enter or Space, and won't submit forms. You'd need to implement all of that behavior yourself. A native <button> does everything automatically.

So when should you actually use ARIA? When native HTML genuinely can't express what you need.

When ARIA is genuinely needed

Despite the "don't use ARIA" rule, modern web applications regularly create interactions that HTML alone can't describe. Here are legitimate use cases:

Custom widgets without native equivalents

HTML has no native tab panel, tree view, combobox with autocomplete, or carousel component. When you build these custom widgets, ARIA roles and properties tell assistive technologies what the component is and how it works.

A tab interface, for example, needs:

  • role="tablist" on the container holding the tab buttons
  • role="tab" on each tab button
  • role="tabpanel" on each content panel
  • aria-selected="true" on the active tab
  • aria-controls linking each tab to its panel

Without these attributes, a screen reader user would just hear a list of buttons with no context about how they relate to the content panels.

Dynamic content updates

When content on a page changes without a full page reload - a notification appearing, a search results list updating, a character count changing - sighted users can see the change. Screen reader users can't, unless you tell their software something changed.

aria-live regions solve this by announcing dynamic content changes:

  • aria-live="polite" - waits for the screen reader to finish its current announcement before reading the update. Use for non-urgent changes like search results or status messages.
  • aria-live="assertive" - interrupts whatever the screen reader is currently saying to announce the update immediately. Use sparingly, only for urgent alerts like error messages or time-sensitive warnings.

A common pattern for form validation:

<div aria-live="polite" role="status">3 results found</div>

Providing additional context

Sometimes a visual interface conveys meaning through layout, proximity, or icons that screen readers can't perceive. ARIA provides attributes to fill these gaps:

  • aria-label - provides a text label when there's no visible text. Useful for icon-only buttons: <button aria-label="Close dialog"><svg>...</svg></button>
  • aria-describedby - points to an element that provides additional descriptive text: <input aria-describedby="password-hint"> with <p id="password-hint">Must be at least 8 characters</p>
  • aria-labelledby - similar to aria-label but references an existing visible element as the label, which is useful when the label text already exists on the page

Key ARIA roles

ARIA roles tell assistive technologies what an element is. They fall into several categories:

Landmark roles

These identify major page regions, letting screen reader users jump directly to sections:

  • role="banner" - the site header (equivalent to <header> when used as a direct child of <body>)
  • role="navigation" - navigation links (equivalent to <nav>)
  • role="main" - the primary content area (equivalent to <main>)
  • role="contentinfo" - the site footer (equivalent to <footer> when used as a direct child of <body>)
  • role="search" - a search form (now available as <search> in HTML)
  • role="complementary" - supporting content (equivalent to <aside>)

Notice that most landmark roles have native HTML equivalents. Prefer the native elements when possible - they provide the same semantics without the need for ARIA.

Widget roles

These identify interactive components that don't exist in native HTML:

  • role="tablist", role="tab", role="tabpanel" - tab interfaces
  • role="dialog", role="alertdialog" - modal and alert dialogs
  • role="menu", role="menuitem" - application-style menus (not navigation menus)
  • role="tree", role="treeitem" - expandable tree views
  • role="slider" - custom range inputs

State and property attributes

These communicate the current state of interactive elements:

  • aria-expanded="true|false" - whether a collapsible section or menu is open
  • aria-selected="true|false" - whether an option is selected (tabs, list items)
  • aria-hidden="true" - hides an element from assistive technologies while keeping it visually present
  • aria-disabled="true" - indicates a disabled state without removing the element from the tab order
  • aria-required="true" - marks a form field as required (though required attribute on native inputs is preferred)
  • aria-invalid="true" - indicates a form field has a validation error

Common ARIA mistakes

Incorrect ARIA is worse than no ARIA at all. These are the mistakes you'll encounter most often:

Redundant ARIA

Adding ARIA roles to elements that already have native semantics is unnecessary and can cause screen readers to announce things twice:

  • <button role="button"> - the <button> element already has an implicit button role
  • <nav role="navigation"> - the <nav> element already has an implicit navigation role
  • <a href="/" role="link"> - links already have an implicit link role

This is harmless in some screen readers but can cause duplicate announcements in others. The fix is simple: remove the redundant role.

Wrong roles

Using a role that doesn't match the element's actual behavior creates confusing experiences:

  • Using role="button" on a link that navigates to a new page - screen reader users expect buttons to perform actions and links to navigate
  • Using role="menu" for a navigation menu - role="menu" is for application-style menus with specific keyboard interaction patterns (arrow key navigation), not for site navigation links
  • Using aria-hidden="true" on focusable elements - this creates a confusing disconnect where keyboard users can focus an element that screen readers can't see

ARIA without behavior

Adding role="button" to a <div> makes screen readers announce it as a button, but it doesn't make it behave like a button. You still need to add tabindex="0" for focus, keyboard event handlers for Enter and Space, and appropriate cursor styling. If you're doing all that work, just use a <button> instead.

How AccessGuard helps with ARIA

AccessGuard's ARIA checker examines your pages for incorrect ARIA usage - redundant roles on native elements, invalid attribute values, missing required properties for widget roles, and aria-hidden on focusable elements. It helps you catch the mistakes that make ARIA harmful rather than helpful, so you can use it with confidence where it's genuinely needed.

Start scanning for free

Join thousands of developers making the web more accessible.

Get started