ARIA Roles
ARIA (Accessible Rich Internet Applications) adds roles and states so assistive tech can understand custom widgets. The catch: the first rule of ARIA is don't use ARIA — a native <button> beats <div role="button"> every time. This sheet is a lookup of the roles/states you'll meet and how to test them. For markup-free testing, see Screen Reader Testing.
The first rule
Use the native element if one exists. <button>, <a href>, <input>, <nav>, <main> come with role, focus, and keyboard behaviour for free. Reach for ARIA only for widgets HTML can't express (tabs, comboboxes, tree views).
Landmark roles (page structure)
| Role | Native element |
|---|---|
banner | <header> |
navigation | <nav> |
main | <main> |
complementary | <aside> |
contentinfo | <footer> |
search | <search> / role="search" |
Widget roles & required state
| Role | Must also have | State to test |
|---|---|---|
button | accessible name | aria-pressed (toggle) |
checkbox / switch | name | aria-checked |
tab | inside tablist | aria-selected, aria-controls |
dialog | aria-modal, label | focus trapped |
combobox | aria-expanded | aria-activedescendant |
alert | — | announced when it appears |
menu / menuitem | arrow-key nav | aria-expanded |
Key states & properties
aria-label / aria-labelledby (name), aria-describedby (extra help), aria-expanded, aria-hidden (hide from AT), aria-live (announce updates), aria-current (current page/step).
Common mistakes
role="button"on adivwithouttabindex="0"+ Enter/Space handlers.aria-labelon an element that isn't focusable/interactive (ignored).aria-hidden="true"on something still focusable — a "ghost" stop.- Redundant roles (
<button role="button">) or wrong roles overriding native semantics. - Setting a role but never updating its state (
aria-expandedstuck onfalse).
// Related resources