Website Spec
Accessibility Recommended Updated 2026-05-29

ARIA — first rule of ARIA

ARIA can make custom widgets accessible, but the first rule of ARIA is don't use ARIA. Reach for a native HTML element first; add ARIA only when nothing native fits.

What it is

ARIA — Accessible Rich Internet Applications — is a set of HTML attributes (role, and the many aria-* attributes) that tell assistive technologies what a custom element is, what state it is in, and how it relates to other elements. ARIA never changes how something looks or behaves; it only affects the accessibility tree.

Why it matters

ARIA is a sharp tool. Used well, it lets you describe widgets the HTML spec does not cover. Used badly, it overrides the real semantics of an element and makes the page less accessible than the unstyled HTML would have been. The W3C’s own guide leads with five rules — and the first is the most important.

How to implement

The five rules of ARIA, in plain English:

  1. Don’t use ARIA if a native HTML element will do. <button>, <a href>, <input type="checkbox">, <details> — these come with role, focus, and keyboard support for free.
  2. Don’t change native semantics. Never write <h1 role="button">. If you need a button, use a <button>.
  3. All interactive ARIA controls must be keyboard-operable. A role="button" div without Space/Enter handlers is broken.
  4. Don’t set role="presentation" or aria-hidden="true" on focusable elements. You will hide controls from the very users who need them.
  5. Every interactive element needs an accessible name. Use a visible label, aria-label, or aria-labelledby.

Common, useful ARIA attributes:

<!-- An icon-only button needs a name -->
<button aria-label="Close">
  <svg aria-hidden="true" focusable="false">…</svg>
</button>

<!-- Associate a hint with an input -->
<label for="pw">Password</label>
<input id="pw" type="password" aria-describedby="pw-hint">
<p id="pw-hint">At least 12 characters.</p>

<!-- Group of toggle buttons sharing a label -->
<div role="group" aria-labelledby="format">
  <h3 id="format">Text format</h3>
  <button aria-pressed="true">Bold</button>
  <button aria-pressed="false">Italic</button>
</div>
  • aria-label overrides the element’s text — use only when there is no visible label.
  • aria-labelledby points at the id of one or more existing elements; it takes precedence over aria-label and <label>.
  • aria-describedby adds a description in addition to the name — for hints, errors, format examples.

Common mistakes

  • role="button" on a <div> with no tabindex, no key handlers, no focus style.
  • Redundant roles: <button role="button">, <nav role="navigation">.
  • aria-label written for SEO, in language different from the visible text — voice control users cannot say the visible text.
  • aria-hidden="true" on a wrapper that contains a focusable button.
  • ARIA states (aria-expanded, aria-checked) never updated by JavaScript when the UI changes.

Verification

  • Inspect every custom widget in the accessibility tree; the role, name, and state must match what is on screen.
  • Run an automated checker for ARIA misuse.
  • Test with a screen reader — the announcement must match how the control behaves.

Related topics

Sources & further reading

Search
esc close navigate open