Skip to main content

ARIA Roles

A role tells assistive technology what an element is. "This is a button." "This is a navigation area." "This is a tab." It is the first thing a screen reader tells you about something, and it decides how a person expects to use it: a button is pressed, a checkbox is toggled, a link is followed.

The key point, which you met in the last lesson, is that native HTML elements already have roles. A button is a button, a nav is a navigation landmark, an h2 is a level 2 heading. The role attribute is for the situations where HTML has no element that fits.


What You Will Learn​

  • What a role is, and how native elements already have them
  • The main families of roles: landmark, widget, live region, structure, and window
  • Which roles are worth knowing
  • What a role promises, and what you must still build
  • Roles to avoid
  • How to check roles

The Big Idea​

index.html
<!-- Native elements already have roles -->
<header>…</header> <!-- role: banner -->
<nav aria-label="Main">…</nav> <!-- role: navigation -->
<main>…</main> <!-- role: main -->
<button type="button">Save</button> <!-- role: button -->
<h2>Ingredients</h2> <!-- role: heading, level 2 -->

<!-- An explicit role fills a gap: there is no HTML tab element -->
<div role="tablist" aria-label="Recipe">
<button role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1">
Ingredients
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">…</div>

<!-- A live region needs a role too -->
<div role="status">Recipe saved.</div>

Browse the list by category, search for an element such as nav, and look at the "Native HTML" line first. Most of the time it says an element exists.

How Roles Work​

  • Every element has a role, either implicit (from the HTML element) or explicit (from the role attribute).
  • An explicit role wins over the implicit one. <div role="button"> is a button to assistive technology, even though it is a div in the code.
  • A role is a promise. It tells people what to expect: a button should respond to Enter and Space, a tab should respond to arrow keys, a dialog should keep focus inside. The role does not keep the promise for you. You must write the behaviour.
  • Each role has rules. Some need a name (dialog, img), some need children of a certain kind (tablist needs tab, list needs listitem), and some need states (checkbox needs aria-checked if it is custom).
  • A role needs to fit the element. The "ARIA in HTML" rules list which roles are allowed on which elements. For example, you may not put role="button" on a heading, or on a link, without changing what the element is.
  • The role attribute can hold a list of words, and browsers use the first one they understand. It is rarely needed, and support is not something to rely on, so use one role.
  • Roles are read by the browser's accessibility tree, which you saw in Introduction to Accessibility.

The Families of Roles​

FamilyWhat it coversExamples
LandmarkBig areas of the pagebanner, navigation, main, search, contentinfo
WidgetThings you interact withbutton, checkbox, tab, slider, combobox
Live regionMessages that changestatus, alert, log, timer
Document structureThe shape of contentlist, heading, img, table, group
WindowPop-up windowsdialog, alertdialog

There is also a group of abstract roles used to define the others. Never use them in your pages.

Landmark Roles​

Landmarks mark the big areas of a page. Screen reader users can list them, or jump between them, much as sighted users glance at the layout. They are the single biggest help for people who need to get to the main content, the search box, or the menu without reading everything in order.

You almost never need the role attribute for them, because HTML elements do the job:

ElementLandmark role
header (directly in the page)banner
navnavigation
mainmain
asidecomplementary
footer (directly in the page)contentinfo
section (with a name)region
form (with a name)form
search, or form role="search"search

Rules of thumb:

  • One main per page, and use header and footer for the page (not for sections).
  • Name repeated landmarks, with aria-label or aria-labelledby: two nav elements need different names.
  • Do not repeat the role in the name: "Main," not "Main navigation."
  • Use section and region sparingly. Too many landmarks are as unhelpful as none.
  • Put everything inside a landmark. Content outside any landmark is easy to miss.
  • A newer search element exists in recent HTML. Support is growing, so check your target browsers, and use role="search" on a form as the safe option.
index.html
<header>…</header>

<nav aria-label="Main">…</nav>

<form role="search" aria-label="Recipes">
<input type="search" aria-label="Search recipes">
<button type="submit">Search</button>
</form>

<main>
<h1>Sourdough</h1>
…
</main>

<aside aria-label="Related recipes">…</aside>

<nav aria-label="Footer links">…</nav>

<footer>…</footer>

Widget Roles​

Widget roles describe interactive things. Native elements cover many of them (button, checkbox, radio, textbox, slider, progressbar, option). A few have no native element, so you need roles to build them: tab, tablist, tabpanel, switch, menu, menuitem, tooltip, and a full combobox.

Using a widget role is a contract. It means you will provide:

  1. A name.
  2. The right states (for example aria-selected on a tab).
  3. The keyboard behaviour people expect (arrow keys inside tabs and menus).
  4. Focus handling (a roving tabindex in a tab list, for instance).
  5. The right structure (tabs inside a tablist).

If you cannot provide all five, do not use the role. A half-built widget confuses people more than a plain one.

warning

menu is not for website navigation. A role="menu" tells a screen reader to switch into a special mode where the arrow keys are the way to move, like an application menu. A site's main menu is a list of links, so use nav, ul, and a.

Live Region Roles​

Some roles tell assistive technology to announce changes to a region, without moving focus. The page must already contain the region, and then you change the text in it.

RoleAnnouncedUse it for
statusPolitely (when the reader is free)"Recipe saved," "3 results found"
alertAt once, and may interruptUrgent errors, "Session ending"
logPolitely, new items addedChat, activity history
timerNot announced as it changesA countdown, with a name

Try them in the lab. If you use a screen reader, you will hear the real thing.

http://127.0.0.1:5500/index.html

role="status" (polite)

role="alert" (assertive)

role="log" (a history)

What a screen reader would do (simulation):

Press a button.

These are real live regions, so if you use a screen reader, you will hear them. The list above is only a plain-text simulation of the difference. Two things matter: the region must already be in the page before its text changes, and an identical message is not announced again. The exact behaviour depends on the screen reader and browser, so test it. Do not use alert for ordinary messages, because it interrupts people.

Choose the gentlest option that works. Most messages should be status, and alert should be rare. Over-using alert is like shouting: it interrupts people, and makes them stop trusting your messages. The next lessons cover live regions in depth, in aria-live.

Structure and Special Roles​

Most structure roles come from HTML: ul and ol (list), li (listitem), h1 to h6 (heading), table, img, figure, hr (separator), article. A few explicit roles are worth knowing:

  • role="img" makes a group of things (an SVG, a few emoji) read as one image, with a name from aria-label.
  • role="group" with a name gathers related controls, such as a set of toolbar buttons. For form fields, prefer fieldset and legend.
  • role="presentation" or role="none" removes the role of an element. It is useful to turn a layout table into plain content, or to hide a li inside a custom widget. Never put it on something focusable or interactive.
  • role="list" on a ul with list-style: none. Some browser and screen reader combinations (notably Safari with VoiceOver) have stopped treating such a list as a list. Adding the role puts it back. This behaviour has changed over time, so check what your audience's browsers do before adding it everywhere.

Roles to Avoid​

  • Abstract roles (such as widget, landmark, command). They are only for the ARIA specification.
  • role="application". It tells screen readers to hand over all the keys to your page, and turn off their own navigation. Almost no page needs it.
  • role="menu" for site navigation. Use a nav with links.
  • A role that repeats the element: <button role="button">, <nav role="navigation">. It does nothing useful, and clutters your code.
  • A role that fights the element: <h2 role="button">, <a role="heading">. Wrap the content instead: <h2><button>…</button></h2>.
  • role="alert" for everyday messages.
  • Interactive roles with no keyboard support (see Accessible Buttons).
  • Roles you do not understand. If you cannot say what a role promises, do not use it.

Check Your Roles​

  1. Open the Accessibility panel in your browser's DevTools, and look at the Role of each element. Does it match what you intended?
  2. List the landmarks with a screen reader, or a browser extension that shows them. Is there one main? Are repeated ones named?
  3. Search your code for role=. For each one, ask: is there a native element? Is the role allowed on this element? Do I provide the name, states, and keys that go with it?
  4. Run an automated checker (axe, Lighthouse) for invalid roles, missing required children, and missing names.
  5. Use the keyboard on every widget role, and listen with a screen reader.
  6. Check the "ARIA in HTML" rules if you are unsure which roles an element may have.

Good Habits​

  1. Use the element with the right role, and add role only to fill a gap.
  2. Use landmark elements, and name the repeated ones.
  3. Treat a widget role as a promise of name, states, keys, and focus.
  4. Follow a tested pattern for tabs, menus, combo boxes, and dialogs.
  5. Choose status before alert.
  6. Never put presentation, none, or aria-hidden on focusable elements.
  7. Keep roles in line with the real behaviour.
  8. Test with a screen reader, and review roles in code review.

Accessibility Checklist​

  • No role is used where a native element does the job.
  • The page has one main, and a header and footer.
  • Repeated landmarks have unique names.
  • Every widget role has a name, the right states, and the right keyboard behaviour.
  • Required parent and child roles are present (such as tablist with tab).
  • dialog and alertdialog have names, and move focus in and out.
  • status is used for normal messages, and alert is rare.
  • menu is not used for site navigation, and application is not used.
  • No focusable element has role="presentation" or role="none".
  • Roles do not repeat or fight the element they are on.

Security and Privacy Notes​

  • Do not announce sensitive data in live regions. A status or alert that reads out an account number, a one-time code, or a password can be overheard.
  • Do not use roles to disguise controls. A control that looks harmless but is announced as something else, or the other way round, is a deceptive pattern, and can hide dangerous actions from people who cannot see the screen.
  • Alerts must be honest. A fake "Security warning" in an alert role, used to push people into clicking, is a scam technique.
  • Be careful with user-supplied text in roles and ARIA values. Never insert unchecked user input into attributes.
  • Role-based detection of screen reader users (by looking for how they use landmarks or live regions) could reveal a disability. Avoid tracking it.
  • Dialogs that ask for consent or privacy choices need proper roles and focus, so that everyone can answer. Hidden or hard-to-reach "reject" buttons are a dark pattern.

Global Audience Notes​

  • Landmark names are text, so translate them (aria-label="Main", aria-label="Footer links") along with the rest of the page.
  • Do not repeat the role name in your label. Screen readers say "navigation" in the user's own language, so "Main navigation" can become a repeated word after translation.
  • Set lang on the page, and on any labels in other languages.
  • Right-to-left languages: arrow-key behaviour in tabs, menus, and toolbars should follow the reading direction. Test it.
  • Live regions in other languages: make sure the message text is in the page's language, and short enough to be understood when read aloud.
  • Different devices: many people use a screen reader on a phone. Roles are understood there too, but some patterns (such as menus and combo boxes) behave differently on touch. Test on mobile.

Common Mistakes to Avoid​

  1. div role="button" with no keyboard support.
  2. role="button" on a button, or role="navigation" on a nav.
  3. A section with no name, expected to be a landmark.
  4. Two nav elements with no names.
  5. role="menu" for a site navigation.
  6. role="application" "to be safe."
  7. role="alert" for every message.
  8. A tablist with no tab children.
  9. role="presentation" on something focusable.
  10. Landmarks nested or repeated without reason.
  11. Content outside any landmark.
  12. Never checking the roles in the Accessibility panel.

Practice Time​

Try these in your browser and your editor:

  1. Browse the role explorer, and find the native element for ten roles.
  2. Use the landmark lab to build a page with no problems, and then break it one way at a time.
  3. Open a page you built, and list its landmarks with a screen reader or an extension.
  4. Add names to two nav elements, and check the Accessibility panel.
  5. Change a layout table to role="presentation", and compare it with using CSS grid.
  6. Use the live roles lab with a screen reader (if you can), and compare status with alert.
  7. Replace three div role="button" elements with real buttons.
  8. Make a role="img" SVG, with a short name.
  9. Search your project for role=, and mark each as "native exists," "fills a gap," or "not sure."
  10. Bonus: read the tabs pattern in the ARIA Authoring Practices Guide, and list the roles, states, and keys it needs.

Quick Recap​

Click a question to check your answer.

1. What is a role?

It tells assistive technology what an element is, such as a button, a navigation area, or a tab, and so how a person should expect to use it.

2. What is the difference between an implicit and an explicit role?

An implicit role comes from the HTML element (a nav is a navigation). An explicit role is set with the role attribute, and it wins over the implicit one.

3. Does adding role="tab" to a button make it behave like a tab?

No. The role is a promise. You must add the states (aria-selected), the keyboard behaviour (arrow keys), and the focus handling yourself.

4. Why name two nav landmarks differently?

So a person browsing the landmark list can tell them apart, for example "Main" and "Footer links."

5. When should you use role="status" and when role="alert"?

Use status for ordinary updates, announced politely. Use alert rarely, for urgent messages that must be announced at once.

6. Why is role="menu" wrong for site navigation?

It switches screen readers to an application-style mode with arrow-key navigation. A website menu is a list of links, so use nav, ul, and a.

Key Takeaways​

  • A role says what something is. Native elements already have the right ones.
  • Landmark elements (header, nav, main, aside, footer) are the easiest big win. Name the repeated ones.
  • A widget role is a promise of a name, states, keys, and focus. Keep it, or do not use the role.
  • Live regions need a role, and must already exist in the page. Prefer status, and use alert rarely.
  • Avoid abstract roles, application, menu for navigation, and roles that repeat or fight the element.
  • Never put presentation, none, or aria-hidden on focusable elements.
  • Check roles in the Accessibility panel, and test with a screen reader.

Next, learn how to describe what things are doing with ARIA States and Properties.