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:
- 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. - Don’t change native semantics. Never write
<h1 role="button">. If you need a button, use a<button>. - All interactive ARIA controls must be keyboard-operable. A
role="button"div without Space/Enter handlers is broken. - Don’t set
role="presentation"oraria-hidden="true"on focusable elements. You will hide controls from the very users who need them. - Every interactive element needs an accessible name. Use a visible label,
aria-label, oraria-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-labeloverrides the element’s text — use only when there is no visible label.aria-labelledbypoints at the id of one or more existing elements; it takes precedence overaria-labeland<label>.aria-describedbyadds a description in addition to the name — for hints, errors, format examples.
Common mistakes
role="button"on a<div>with notabindex, no key handlers, no focus style.- Redundant roles:
<button role="button">,<nav role="navigation">. aria-labelwritten 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
- ARIA Authoring Practices Guide — Read Me First — W3C WAI
- Using ARIA — W3C
- MDN — ARIA — MDN
- WCAG 4.1.2 — Name, Role, Value (Level A) — W3C