ARIA Roles Reference

All WAI-ARIA roles with required/allowed attributes and accessible name source.

A searchable WAI-ARIA role reference covering landmark, widget, document-structure and live-region roles, each with its required attributes or context and where its accessible name comes from. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is the first rule of ARIA?

Do not use ARIA if a native HTML element or attribute already gives you the role, state and behaviour you need. A <button> is more robust and accessible than a <div role="button"> that you have to wire up with keyboard handlers and aria-pressed yourself.

This is a searchable reference for WAI-ARIA roles — the role tokens that describe what an element is to assistive technology. It groups them into landmark roles (page regions), document-structure roles (lists, tables, headings), widget roles (buttons, checkboxes, comboboxes, tabs) and live-region roles (alerts and status messages), and for each shows the attributes or context it requires and where its accessible name comes from.

How roles work

A role is applied with the role attribute and tells the accessibility tree how to expose an element. Most native HTML elements already carry an implicit role<button> is button, <nav> is navigation — so you rarely need to set role explicitly. When you build a custom widget from generic elements, the role brings obligations: many roles require specific attributes (a checkbox needs aria-checked, a slider needs aria-valuenow/aria-valuemin/aria-valuemax, a heading needs aria-level) and composite roles require a child contract (a tablist must own tab children). The name-from column captures how the element’s accessible name is computed: some roles derive it from their text contents, while others require an explicit aria-label, aria-labelledby or associated <label>.

Role categories at a glance

Landmark roles

Landmarks mark out the major navigable regions of a page. Screen-reader users can jump between them with a single keystroke, so using them correctly is high-impact for keyboard navigation:

RoleNative HTML equivalentNotes
banner<header> (when direct child of <body>)Page-level header; one per page
navigation<nav>Label with aria-label when multiple exist
main<main>One per page; primary content
complementary<aside>Related but secondary content
contentinfo<footer> (when direct child of <body>)Site-level footer
search<search> (HTML 5.2+)Wrap search forms in this
region<section> with an accessible nameRequires a label to be exposed as a landmark

Widget roles (selected)

RoleRequired attributesKey behaviour to implement
buttonNone (name required)Enter and Space activate; toggle with aria-pressed
checkboxaria-checkedSpace toggles; tristate uses "mixed"
comboboxaria-expanded, aria-controlsConnects to a listbox or grid popup
slideraria-valuenow, aria-valuemin, aria-valuemaxArrow keys change value
switcharia-checkedSame as checkbox but semantically on/off
tablisttabtabpanelaria-selected, aria-controlsArrow keys move between tabs

Live-region roles

Live regions cause screen readers to automatically announce dynamic content changes:

  • alert — assertive; interrupts the current reading. Use only for time-sensitive errors or warnings. Maps to aria-live="assertive".
  • status — polite; waits for user to finish. Suitable for form success messages. Maps to aria-live="polite".
  • log — for chronological content like chat; polite by default.
  • timer — for countdown or elapsed-time displays; usually has no implicit live behaviour (set aria-live manually).

Practical examples

<!-- Native is better than ARIA -->
<button type="button">Save</button>

<!-- A custom toggle switch done correctly -->
<span role="switch" tabindex="0" aria-checked="false" aria-label="Dark mode">
</span>

<!-- Tab panel pattern (simplified) -->
<div role="tablist" aria-label="Settings sections">
  <button role="tab" aria-selected="true" aria-controls="panel-general" id="tab-general">General</button>
  <button role="tab" aria-selected="false" aria-controls="panel-privacy" id="tab-privacy">Privacy</button>
</div>
<div role="tabpanel" id="panel-general" aria-labelledby="tab-general">...</div>
<div role="tabpanel" id="panel-privacy" aria-labelledby="tab-privacy" hidden>...</div>

<!-- Alert for form errors -->
<div role="alert">Your session has expired. Please save your work.</div>

Common pitfalls

  • Not managing focus — adding role="dialog" does not move focus into the dialog. You must do that in JavaScript when the dialog opens.
  • Nested interactive roles — putting a button inside a link or nesting tablist inside tablist creates invalid hierarchies.
  • Using role="presentation" on functional elements — this strips semantics but does not prevent interaction, leaving keyboard users with unlabelled focusable elements.
  • Repeated landmarks without labels — two <nav> elements on the same page both expose as navigation; use aria-label to distinguish them (“Main navigation” vs “Footer navigation”).

Everything runs in your browser; nothing you search is uploaded.