ARIA (Accessible Rich Internet Applications)
What is ARIA?
ARIA (Accessible Rich Internet Applications) is a set of attributes you add to HTML so assistive technologies (e.g. screen readers) can understand roles, states, and relationships that native HTML doesn’t provide. Use ARIA when you build custom widgets (tabs, dialogs, menus) or when you need to expose dynamic state (expanded, selected, invalid). Prefer semantic HTML when it already does the job.
Use it when: you have custom interactive components (e.g. a div that acts as a button, a custom dropdown, a modal) and need to expose their role, name, state, and keyboard behaviour to assistive tech. Don’t use ARIA to fix bad structure; fix the HTML first.
Copy/paste checklist (when using ARIA)
- [ ] Prefer HTML – Use
- [ ] Role – role="button", role="dialog", role="tablist", etc. so the control is announced correctly.
- [ ] Name – aria-label or aria-labelledby so the element has an accessible name.
- [ ] State – aria-expanded, aria-selected, aria-checked, aria-invalid, etc. so current state is announced.
- [ ] Relationships – aria-controls, aria-describedby, aria-owns where they help (e.g. button controls panel).
- [ ] Keyboard – Implement keyboard navigation and focus management that match the role (e.g. dialog: trap focus, Escape closes).
- [ ] Don’t override semantics – Don’t add role="button" to a
Why ARIA matters
- Custom UI (divs and spans with JavaScript) has no meaning for assistive tech without ARIA (or without replacing it with semantic HTML).
- WCAG 4.1.2 (Name, Role, Value) requires that widgets have an accessible name, role, and state; ARIA is how you provide them for custom components.
- Screen reader users need correct role and state announcements to use tabs, dialogs, and menus.
- ARIA doesn’t change behaviour; you must still implement keyboard and focus management yourself.
What good ARIA use includes
Checklist
- [ ] Only when needed – Use semantic HTML first; ARIA only for custom widgets or when HTML can’t convey the same.
- [ ] Correct role – Use a role that matches the behaviour (e.g. role="dialog" for a modal, not role="alert").
- [ ] Name – Every interactive element has an accessible name (visible text, aria-label, or aria-labelledby).
- [ ] State in sync – aria-expanded, aria-selected, etc. match the actual UI state; update them when state changes.
- [ ] Keyboard and focus – Keyboard navigation and focus management follow the pattern for that role (see ARIA Authoring Practices Guide).
- [ ] Tested – Test with a screen reader so role, name, and state are announced correctly.
Common patterns
- Custom button: role="button", tabindex="0", aria-label or visible text; Enter and Space activate.
- Dialog: role="dialog", aria-modal="true", aria-labelledby (and optionally aria-describedby); focus trap; Escape closes.
- Tabs: role="tablist", role="tab", role="tabpanel"; aria-selected, aria-controls; arrow keys and Tab per pattern.
- Live updates: aria-live="polite" or "assertive" for regions that update (e.g. errors, success messages).
Examples
Example (the realistic one)
Custom “Save” control: It’s a div with a click handler. You add role="button", tabindex="0", aria-label="Save changes", and key handler for Enter and Space. You don’t use a
Common pitfalls
- ARIA on semantic HTML: role="button" on a
- Missing keyboard: ARIA role without matching keyboard behaviour. → Do this instead: Implement the keyboard pattern for that role (see ARIA APG).
- State not updated: aria-expanded stays true after closing. → Do this instead: Update ARIA state whenever the UI state changes.
- No accessible name: role="dialog" but nothing says what the dialog is. → Do this instead: Use aria-labelledby (and optionally aria-describedby) so the dialog has a name.
- Overusing ARIA: Fixing everything with ARIA instead of fixing bad HTML. → Do this instead: Use semantic HTML first; use ARIA only when necessary.
ARIA vs. related concepts
- ARIA vs semantic HTML: Semantic HTML (button, nav, main, label) gives role and behaviour for free. ARIA supplements when you can’t use the right HTML (e.g. custom widget).
- ARIA vs keyboard: Keyboard navigation is behaviour you implement; ARIA exposes role and state. Both are needed for custom components.
- ARIA vs screen reader: Screen reader compatibility is the outcome; ARIA is one way to achieve it for custom UI.
Related terms
- Screen reader compatibility – ARIA helps screen readers understand custom UI.
- Keyboard navigation – implement keyboard behaviour that matches ARIA role.
- Focus management – dialogs and dynamic content need focus + ARIA.
- WCAG – 4.1.2 Name, Role, Value.
- Accessibility – ARIA is part of accessible custom components.
- ARIA Authoring Practices Guide (APG) – patterns for roles and keyboard.
Next step
Audit one custom component (e.g. a dropdown or modal). If it’s not using semantic HTML, add the correct ARIA role, name, and state, and implement the keyboard and focus behaviour from the ARIA APG. Test with a screen reader. Prefer replacing the custom control with a native element (button, select, dialog) where possible.