Introduction to ARIA
So far in this section you have used plain HTML to make pages accessible: real headings, real buttons, real labels, real tables. That is the best foundation, and it will carry you a long way. But sometimes HTML alone is not enough. A tab panel, a live "Saved!" message, an icon-only button: these need a little extra help to tell assistive technology what is going on.
That help is ARIA. It is powerful, and easy to misuse. This lesson explains what ARIA is, what it can and cannot do, and the few rules that keep you out of trouble. The next lessons look at the main parts one by one.
What You Will Learnβ
- What ARIA stands for, and what it does
- The three kinds of ARIA: roles, properties, and states
- The five rules of ARIA
- Why native HTML comes first
- What ARIA cannot do
- When you really need ARIA
- How to check your ARIA
The Big Ideaβ
- HTML Code
- ARIA Behaviour Lab
<!-- Native HTML: no ARIA needed -->
<button type="button">Save</button>
<!-- ARIA gives a name to an icon-only button -->
<button type="button" aria-label="Close">
<svg aria-hidden="true" focusable="false">β¦</svg>
</button>
<!-- ARIA carries a state -->
<button type="button" aria-expanded="false" aria-controls="panel">
Delivery details
</button>
<div id="panel" hidden>β¦</div>
<!-- ARIA announces a change -->
<div role="status">Recipe saved.</div>
<!-- A made-up button: role only, no behaviour! -->
<div role="button">Save</div>
A div with role="button"
- Reached by Tab: 0
- Mouse clicks: 0
- Enter received: 0
- Space received: 0
- Times it did its job: 0
A real button
- Reached by Tab: 0
- Clicks (mouse, Enter, or Space): 0
- Enter received: 0
- Space received: 0
- Times it did its job: 0
Press Tab to move through the page, and try Enter and Space on each one. To a screen reader, both are "button" (that is what role="button" does). But the made-up one starts with no keyboard support at all: Tab skips it, and Enter and Space do nothing. ARIA changed what it is called, not what it does. You have to add the focus and the key handling yourself, and then you have rebuilt, in more code, what the real button gave you for free. (Counts are for this demo only. Some screen readers have their own ways to activate items, so they may behave differently.)
Try the lab first with both boxes unticked, then tick them one at a time. You will see how much work a real button does that a div with ARIA does not.
What Is ARIA?β
ARIA stands for Accessible Rich Internet Applications. (You will also see WAI-ARIA, from the W3C's Web Accessibility Initiative.) It is a set of attributes you add to HTML elements to give assistive technology more information:
- Roles say what something is (
role="tablist"). - Properties describe it (
aria-label="Close",aria-controls="menu"). - States say what it is doing right now (
aria-expanded="true",aria-pressed="false").
Think of ARIA as a note stuck on the accessibility tree (see Introduction to Accessibility). It changes what a screen reader hears, and nothing else.
What ARIA Does Not Doβ
- It does not add behaviour.
role="button"makes something sound like a button. It does not make it focusable, or give it Enter and Space support, as the lab showed. - It does not change how things look. A
divwithrole="heading"is not bigger or bolder. - It does not fix the focus order or the keyboard.
- It does not work magic on its own. Support varies between browsers and screen readers, and a wrong role can make things worse than none.
You may hear "No ARIA is better than bad ARIA." Large surveys of home pages (such as the WebAIM Million) have repeatedly found that pages with ARIA tend to have more detected accessibility errors than pages without it. That does not mean ARIA is bad. It means ARIA is easy to get wrong, and a wrong role is worse than a missing one. Use it with care, and test.
The Five Rules of ARIAβ
The W3C's guide to using ARIA boils everything down to five rules:
- If you can use a native HTML element or attribute with the meaning and behaviour you need, use it, instead of adding ARIA. (Use
button, notdiv role="button".) - Do not change native semantics, unless you really have to. (Do not write
<h2 role="button">. Put abuttoninside the heading.) - All interactive ARIA controls must be usable with the keyboard. If you make a
role="button", it must be focusable and respond to Enter and Space. - Do not use
role="presentation"oraria-hidden="true"on a focusable element. It would be reachable by keyboard, but invisible to a screen reader. - All interactive elements must have an accessible name. See Accessible Names.
If you remember only one thing, remember rule 1.
Native HTML Firstβ
Almost every ARIA role you meet has a native equivalent that is better:
| Instead of this | Use this |
|---|---|
div role="button" | button |
div role="link" | a href |
div role="navigation" | nav |
div role="main" | main |
div role="heading" aria-level="2" | h2 |
div role="list" and listitem | ul and li |
div role="checkbox" | input type="checkbox" |
div role="dialog" | dialog |
aria-required="true" | required |
aria-disabled on a form field | disabled |
Native elements come with focus, keyboard support, a role, a name, and a state, all tested by browser makers for years. ARIA is for the gaps where HTML has no native answer.
Roles, Properties, and Statesβ
Here is a map of the ARIA you will meet. Each group gets its own lesson soon.
| Kind | What it does | Examples |
|---|---|---|
| Roles | Say what something is | tablist, dialog, status, alert, search |
| Properties | Describe and connect things | aria-label, aria-labelledby, aria-describedby, aria-controls |
| States | Change as people use the page | aria-expanded, aria-pressed, aria-checked, aria-selected, aria-hidden, aria-current |
| Live regions | Announce changes | aria-live, role="status", aria-atomic |
How the Syntax Worksβ
- Every ARIA attribute begins with
aria-, and the role is the plainroleattribute. - True and false are words:
aria-expanded="true"andaria-expanded="false". Write them as strings, with the quotes. - Some values come from a fixed list:
aria-live="polite",aria-current="page",aria-pressed="mixed". - Some values are the
idof another element:aria-labelledby="title",aria-controls="menu". The id must exist. - Some are plain text:
aria-label="Close". Write it in the page's language. - States must be kept up to date with script. If a panel opens and
aria-expandedstill saysfalse, ARIA is now lying to people. - A missing attribute and a
falsevalue can mean different things for some attributes (for examplearia-pressed: not a toggle at all, or a toggle that is off). Follow the rules for each attribute.
Do You Need ARIA?β
Use the guide below on things you are building. Notice how many answers are "Not needed."
- HTML Code
- Do I Need ARIA?
<!-- Not needed: native -->
<label for="email">Email address (required)</label>
<input id="email" type="email" required>
<!-- A little: a missing name, and a hidden icon -->
<button type="button" aria-label="Close">
<svg aria-hidden="true" focusable="false">β¦</svg>
</button>
<!-- A little: the current page -->
<a href="/recipes" aria-current="page">Recipes</a>
<!-- Yes: a message that appears -->
<div role="status">Recipe saved.</div>
Do you need ARIA? Not needed
A native button already has the role, focus, keyboard support, and a name.
<button type="button">Save</button>Go down the list from top to bottom. The more custom your widget, the more ARIA it needs, and the more you must test it.
Where to Learn the Patternsβ
When you must build a custom widget (tabs, a menu, a combobox, an accordion), do not invent the ARIA yourself. Follow a tested pattern, such as those in the WAI-ARIA Authoring Practices Guide (APG). It lists the roles, states, and keyboard keys for each widget, with examples.
Even a good pattern needs testing, because screen reader support differs. A pattern that works well in one combination (say, a screen reader and browser on Windows) may behave differently on a phone. Test with the combinations your audience really uses.
Check Your ARIAβ
The checker below finds common mistakes: unknown roles and attributes, bad values, references to ids that do not exist, aria-hidden on focusable things, made-up buttons that cannot be focused, redundant roles, and aria-label on plain div or span elements.
On a real site, also:
- Search your code for
role=andaria-. For each one, ask: could a native element do this? - Use the browser's Accessibility panel to check the role, name, and state of each widget.
- Run an automated checker (such as axe or Lighthouse) to catch invalid ARIA.
- Use the keyboard on every ARIA widget. Can you reach it, and operate it?
- Listen with a screen reader. Do the name, role, and state sound right, and do they update?
Good Habitsβ
- Reach for native HTML first, every time.
- Add ARIA only to fill a real gap.
- Keep ARIA states up to date with script.
- Make every ARIA control work with a keyboard.
- Never hide a focusable element with
aria-hidden. - Follow a tested pattern for custom widgets.
- Check that every id you reference exists.
- Write names in the page's language, and keep them short.
- Test with real assistive technology, and review ARIA in code review.
Accessibility Checklistβ
- No ARIA is used where a native element or attribute would do.
- Every ARIA role is valid, and suits the element.
- Every custom widget can be focused and used with a keyboard.
- No focusable element has
aria-hidden="true"orrole="presentation". - Every interactive element has an accessible name.
- ARIA states (
aria-expanded,aria-pressed, and so on) change when the widget changes. - Every id used in
aria-labelledby,aria-describedby, andaria-controlsexists. - ARIA values are valid, and spelled correctly.
- Custom widgets follow a known pattern, and were tested with a screen reader.
- The ARIA has been checked with an automated tool, and by a person.
Security and Privacy Notesβ
- Do not put private data in ARIA attributes. Values such as
aria-labelcan be read aloud, read by browser extensions, and seen in the page source. Do not include passwords, personal identifiers, or hidden information. - Do not use ARIA to mislead. A name that does not match what a control really does (for example "Cancel" on a button that confirms a purchase) is deceptive, and harms people who rely on it.
- Be careful what you announce. A live region that reads out sensitive information (a one-time code, an account balance, a typed password) could be overheard by someone nearby.
- Do not use
aria-hiddento hide important warnings, security messages, or legal notices from screen reader users. - Do not detect or track assistive technology use by looking for ARIA behaviour or settings. It can reveal a disability.
- Test that ARIA cannot be abused if you render content from users. Never insert user-supplied text into
roleoraria-*attributes without cleaning it first.
Global Audience Notesβ
- Translate ARIA text. Values such as
aria-label,aria-description, andaria-roledescriptionare part of your content. Include them in your translation process, and test with the tools your audience uses. - Set the page language with
lang, so screen readers pick the right voice for the names ARIA supplies. - Avoid
aria-roledescriptionunless you have a clear need. A custom description is read in your words, and may be wrong in other languages, or confuse people who know the usual role names. - Right-to-left languages: arrow-key patterns (tabs, menus, sliders) should follow the reading direction. Test them in a right-to-left layout.
- Assistive technology differs by region and device. Many people use a screen reader on a phone, and some use older or free tools. Test on both a desktop and a mobile screen reader, and keep your markup simple.
- Simple wording in ARIA labels translates best, and is easier for people reading in a second language.
Common Mistakes to Avoidβ
divorspanwithrole="button"and no keyboard support.- Putting ARIA on everything, "just in case."
- Adding
role="button"to abutton, orrole="navigation"to anav. aria-hidden="true"on a focusable element.- States that never change, such as
aria-expandedstuck onfalse. - Pointing to ids that do not exist.
- Misspelled roles and attributes (
aria-lable). - Invalid values (
aria-expanded="yes"). - Using
aria-labelon a plaindivorspan. - Using ARIA to repair bad HTML instead of fixing the HTML.
- Inventing your own widget patterns.
- Never testing with a screen reader.
Practice Timeβ
Try these in your browser and your editor:
- Use the behaviour lab with both boxes unticked, and press Tab, Enter, and Space. Describe what happens.
- Tick the boxes one at a time, and note how much extra work the made-up button needs.
- Go through every item in the "Do I need ARIA?" guide, and say which are native.
- Run the checker on the messy page, fix every problem, and run it again.
- Find three places in a project where you use
role=oraria-. Could a native element do the job? - Replace a
div role="button"with a realbutton. - Open the Accessibility panel, and look at the role, name, and state of a button, a link, and a checkbox.
- Add
aria-current="page"to the current link in a menu. - Make a "Saved" message with
role="status", and trigger it from a button. - Bonus: read the APG pattern for tabs, and list every role, state, and key it needs.
Quick Recapβ
Click a question to check your answer.
1. What does ARIA stand for, and what does it do?
Accessible Rich Internet Applications. It adds roles, properties, and states that tell assistive technology more about an element.
2. What is the first rule of ARIA?
If a native HTML element or attribute can do the job, use it, and do not add ARIA.
3. Does role="button" make a div work like a button?
No. It only changes what assistive technology announces. You still have to add focus, and Enter and Space support, yourself.
4. What are the three kinds of ARIA attributes?
Roles (what it is), properties (what it is like, and what it relates to), and states (what it is doing right now).
5. Why must you never put aria-hidden="true" on a focusable element?
Keyboard users could still reach it, but screen reader users would not know it exists.
6. When do you need ARIA?
When HTML has no native answer: custom widgets such as tabs, live messages, extra states such as aria-expanded, and missing names for icon-only controls.
Key Takeawaysβ
- ARIA adds meaning, not behaviour. It changes what assistive technology hears, and nothing else.
- Native HTML first. It is shorter, tested, and more reliable.
- Roles, properties, and states are the three parts of ARIA.
- Follow the five rules, especially: keyboard support, no hiding focusable things, and an accessible name for everything interactive.
- Keep states up to date, and make sure referenced ids exist.
- Copy tested patterns for custom widgets, and do not invent your own.
- Test with a keyboard and a screen reader. Bad ARIA is worse than none.
Next, learn what roles do, and which ones are worth knowing, in ARIA Roles.