What is ARIA?
ARIA: ARIA (Accessible Rich Internet Applications) is a W3C set of HTML attributes that tells assistive technology what custom UI elements are and their state.
ARIA, formally WAI-ARIA, is a set of attributes defined by the W3C that add meaning to HTML where native elements fall short. A screen reader builds its picture of a page from the accessibility tree, which the browser derives from your markup. A <button> arrives in that tree with a role, a name and keyboard behavior for free. A <div> styled to look like a tab arrives as nothing. ARIA lets you describe that div as a tab, say whether it is selected, and point to the panel it controls. It changes what assistive technology announces. It does not change behavior: no ARIA attribute adds focusability, keyboard handling or click events.
How it works
ARIA has three kinds of attributes. Each one is a promise to the user, and the script behind the element has to keep it.
- Roles declare what an element is:
role="dialog",role="tablist",role="switch",role="status". A role implies a contract, such as arrow keys moving between tabs. - States describe values that change with interaction:
aria-expanded,aria-selected,aria-checked,aria-disabled,aria-invalid. - Properties describe labels and relationships that change less often:
aria-label,aria-labelledby,aria-describedby,aria-controls,aria-live.
The W3C ARIA Authoring Practices Guide (APG) documents the expected roles, states and keyboard interactions for common widgets such as dialogs, menus, tabs, comboboxes and tree views. It is the reference to check when you build one yourself. A disclosure button is the smallest useful example:
<button
type="button"
aria-expanded={open}
aria-controls="filters-panel"
onClick={() => setOpen(!open)}
>
Filters
</button>
<div id="filters-panel" hidden={!open}>
{/* filter fields */}
</div>
Common pitfalls
The first rule of ARIA use, from the W3C, is to prefer a native element whenever one exists. WebAIM's yearly audit of the top million home pages keeps finding that pages using ARIA average more detected accessibility errors than pages without it. Incorrect ARIA is worse than none, because it tells users something false with full confidence.
- Adding
role="button"to adivwithouttabIndex={0}and Enter and Space handlers. It is announced as a button and cannot be operated from a keyboard. - Putting
aria-hidden="true"on an element that contains focusable children. Keyboard users land on something screen readers claim does not exist. - Letting state attributes drift: an
aria-expandedthat staysfalseafter the panel opens is a false statement. - Using
aria-labelon elements with no role, such as a plainspan, where many screen readers ignore it. - Labeling icon buttons with a tooltip only. Give the button an accessible name with
aria-labelor visually hidden text.
How MiniDev UI uses it
Interactive primitives such as Dialog, Tabs and Accordion are built on Base UI, which applies the roles, states and keyboard handling from the APG patterns. You provide names and content. For text that only screen readers should hear, use VisuallyHidden; to let keyboard users jump past the navigation, add SkipLink as the first focusable element. Pair all of this with a visible focus style (see :focus-visible) so sighted keyboard users can follow along.
DialoguiShadcn compatible modal dialog on Base UI with a blurred backdrop, enter and exit animation, close button, header, title, description and a footer bar.npx shadcn@latest add ui.minidev.pro/r/dialog.jsonVisually HiddenuiVisually hidden wrapper that keeps content available to screen readers while hiding it on screen via sr-only. Use it for icon button labels and extra context.npx shadcn@latest add ui.minidev.pro/r/visually-hidden.json