WAI-ARIA: Making Rich Interfaces Accessible
Ah, ARIA. Probably the most misunderstood topic in web accessibility. WAI-ARIA is a W3C specification that adds semantic metadata to HTML elements so assistive technologies can understand them. Confession: I misunderstood this for years before it really clicked.
The fundamental thing to remember: ARIA changes neither appearance nor behavior. It only adds invisible labels that screen readers can interpret. Your component looks the same, acts the same, but the screen reader finally knows what it is.
The 3 Components
Roles: "What is this element?"
Landmarks (navigation, main, banner), widgets (button, dialog, tab, slider), structure (list, table, heading), and live regions (alert, status, timer). They tell assistive tech what kind of thing it's dealing with.
Properties: "What does this element have?"
aria-label for invisible labels, aria-labelledby to point to a visible label (prefer this when one exists), aria-describedby for additional descriptions, aria-controls to say "this button controls that element over there", aria-required for mandatory fields.
States: "What's the current status?"
aria-expanded (open/closed), aria-selected (selected or not), aria-checked (checked/unchecked/mixed), aria-hidden (hidden from assistive tech — this one causes a lot of bugs when misused), aria-invalid (field has errors).
The 5 Golden Rules
These are non-negotiable:
- Don't use ARIA if native HTML works: a
<button>is ALWAYS better than<div role="button">. Always. - Don't override native semantics: putting role="button" on an h2 is an accessibility crime
- All ARIA components must be keyboard-operable: if you add role="button", handle Enter and Space
- Never aria-hidden on focusable elements: the focus "disappears" and users get lost
- Every interactive element needs an accessible name: via label, aria-label, or aria-labelledby
Common Mistakes (I See These Everywhere)
- Redundant ARIA:
<nav role="navigation">— unnecessary, nav already has that implicit role - aria-label on non-interactive elements: aria-label on a div without a role? Screen readers ignore it completely. Dead code.
- aria-hidden on visible content: hiding something from screen readers that sighted users can see. That's creating an unequal experience.
- Roles without keyboard support: role="button" without handling Enter and Space. The screen reader says "button" but pressing Enter does nothing.
When to Actually Use ARIA
ARIA isn't the enemy — it's a last resort for cases HTML can't handle natively: complex components (tabs, modals, tree views), dynamic updates (aria-live), connecting distant DOM elements (aria-describedby), hiding decorative content (aria-hidden on a purely visual icon).
"No ARIA is better than bad ARIA." I say this to every developer I mentor. Misused ARIA can make a site LESS accessible than plain HTML with no ARIA at all. Use it wisely, or don't use it.