ARIA & Accessibility Field Guide
Native-first implementation reference · v1.1 · July 17, 2026

Implementation handbook

ARIA is a contract, not decoration.

Use native HTML first. Add ARIA only when semantics, states, or relationships are otherwise missing. Every explicit role carries a keyboard, focus, state, and testing obligation.

No ARIA is better than bad ARIA.

An incorrect role can override reliable browser semantics and create a false interaction model for assistive technology.

1st Choose the native element
2nd Add only missing semantics
3rd Implement the interaction contract
4th Test the accessibility tree

01 · Decision model

Choose semantics before styling

Follow this sequence for every interactive component. A visual design should not determine the role.

Identify the user task

Is the user navigating, submitting, selecting, toggling, expanding, editing, or issuing an application command?

Select native HTML

Prefer button, a, input, select, details, dialog, and table.

Find the semantic gap

Add only the missing name, state, relationship, live announcement, or custom-widget role.

Implement behavior

Match keyboard navigation, focus movement, activation, cancellation, selection, and disabled behavior.

Synchronize state

The visual state, DOM state, ARIA state, and application state must describe the same condition.

Validate with users and tools

Inspect keyboard operation, focus order, announcements, zoom, reflow, contrast, and real assistive technology.

A role is a promise.

role="button" promises button behavior. It does not create Enter or Space activation, focusability, disabled behavior, or form semantics.

02 · Role catalog

Roles by implementation cost

Search the catalog by role, native equivalent, required behavior, or category.

Showing all roles.

ARIA role catalog with native alternatives and implementation obligations
Role Category Native first Use when Primary obligation
button Widget <button> A non-native element must act as a button. Focus, Enter and Space activation, disabled behavior.
checkbox Widget <input type="checkbox"> A custom binary or tri-state selection is unavoidable. aria-checked, Space activation, label, focus.
radio Widget <input type="radio"> A custom mutually exclusive option is unavoidable. Group semantics, checked state, arrow-key model.
switch Widget Checkbox or button The binary state is explicitly understood as on or off. aria-checked, stable label, immediate state change.
slider Widget <input type="range"> A custom continuous-value control is essential. Arrow/Home/End keys, min/max/current value, orientation.
tablist Composite Buttons may be sufficient Mutually exclusive panels share one local context. Roving focus, arrow keys, selection and panel linkage.
menu Composite Disclosure plus links An application command menu behaves like desktop software. Managed focus, arrow keys, Escape, type-ahead.
listbox Composite <select> Native select cannot meet the interaction requirement. Managed focus, selection, type-ahead, option ownership.
combobox Composite Input plus datalist/select An editable or selectable popup requires custom behavior. Popup state, focus strategy, active option, keyboard model.
grid Composite <table> Cells are interactive like a spreadsheet. Two-dimensional focus, row/cell semantics, edit mode.
main Landmark <main> Normally implicit through native HTML. One primary main landmark per rendered page.
navigation Landmark <nav> Identify a significant navigation group. Distinct labels when multiple navigation landmarks exist.
search Landmark <search> or labelled form Identify site or application search. Clear landmark name when multiple search regions exist.
region Landmark Named <section> Content is a significant navigation destination. Accessible name and restraint to avoid landmark overload.
heading Structure <h1><h6> Usually only for environments without native headings. Correct level and document outline.
list Structure <ul> or <ol> Native list markup is unavailable. Correct list-item ownership and meaningful grouping.
status Live region No direct equivalent Routine dynamic information should be announced politely. Update an existing region; do not move focus.
alert Live region No direct equivalent An urgent condition requires immediate awareness. Use sparingly; avoid interrupting routine work.
dialog Window <dialog> A focused task appears in a separate window context. Name, initial focus, containment, Escape, focus return.
alertdialog Window <dialog> A brief urgent decision requires immediate response. Concise message, explicit choices, disciplined focus.
command Abstract Never author directly Only defines the ARIA ontology. Do not use abstract roles in content.

03 · State model

Names, states, and relationships

Roles answer “what is this?” These attributes communicate identity, condition, and connection.

Common ARIA state and relationship attributes
Attribute Purpose Typical use Critical rule
aria-labelledby Names an element using visible text elsewhere. Dialog, region, control group. Prefer visible labels over hidden-only names.
aria-describedby Adds supplementary description. Help text, constraints, validation explanation. Do not use description as a substitute for a label.
aria-expanded Reports whether controlled content is open. Disclosure, accordion, menu button. Place it on the controlling element and synchronize it.
aria-controls Identifies controlled content. Disclosure, tabs, accordion. It describes a relationship; it implements no behavior.
aria-current Marks the current item in a related set. Page, step, date, location. Do not confuse current with selected.
aria-selected Marks selection inside a composite widget. Tab, option, grid cell. Selection and keyboard focus may be different states.
aria-pressed Reports a toggle-button state. Bold, mute, pin, favorite. Keep the button label stable while the state changes.
aria-checked Reports checkbox, radio, or switch state. Custom selection controls. Native checked state is preferable when available.
aria-invalid Reports a value that failed validation. Form field. Connect the field to a specific error message.
aria-busy Reports that a region is being updated. Refreshing results or data panels. Clear it when the update is complete.
Never publish contradictory state.

checked plus aria-checked="false" creates an invalid state model. Native HTML state takes priority.

04 · Runnable patterns

Interaction contracts in practice

These examples are deliberately small. Each demonstrates the semantic baseline, state owner, keyboard behavior, and focus strategy.

Disclosure navigation

Use for ordinary website navigation. Do not convert a group of links into an application menu.

Low complexity
Native foundation
Button plus ordinary links.
State
aria-expanded on the button mirrors hidden on the panel.
Keyboard
Native button activation. Links remain in normal Tab order.
Focus
Remains on the trigger when toggled.
<button
  type="button"
  aria-expanded="false"
  aria-controls="resources-panel"
>
  Resources
</button>

<div id="resources-panel" hidden>
  <a href="/guides">Guides</a>
</div>

Tabs

Use only for mutually exclusive panels. A row of content filters is not automatically a tab interface.

Composite widget
Start with the native element and document the remaining semantic gap.
Role structure
tablist owns tab elements; each tab controls a tabpanel.
State
One tab has aria-selected="true"; inactive tabs use tabindex="-1".
Keyboard
Arrow keys, Home, and End use roving focus. This example automatically activates on focus.
Focus
One Tab stop enters the tab list.

Native dialog

Native dialog provides the window primitive. The application still owns naming, focus placement, cancellation, and return.

Window
Native foundation
<dialog> opened with showModal().
Name
aria-labelledby references the visible heading.
Keyboard
Escape closes. Tab remains within the modal browser context.
Focus
Initial focus moves to the heading; focus returns to the invoker.

Status message

Routine updates should be announced without moving focus or interrupting the user.

Live region
No recent status message.
Role
status supplies polite live-region behavior.
Update
Change the text of an existing region after the action.
Focus
Never move focus merely to expose a routine message.

Custom switch

Use when the product language clearly describes an immediate on/off setting. A native checkbox is still the safer default.

Custom widget
Announce deployment completion

Setting is off.

Foundation
Native button activation plus explicit switch semantics.
State
aria-checked changes; the visible label remains stable.
Keyboard
Enter and Space come from the native button.

05 · Page structure

Landmarks should reveal the information architecture

Landmarks are navigation destinations, not visual containers. Too many named regions produce a noisy, flat page map.

Recommended shell

  • One primary <main>.
  • Significant navigation groups use <nav>.
  • Multiple navigation landmarks receive distinct names.
  • Named sections represent meaningful destinations.
  • A skip link reaches the main content.

Do not create landmark noise

  • Do not turn every card into a region.
  • Do not add role="main" to <main>.
  • Do not use <nav> for every list of links.
  • Do not leave repeated navigation landmarks unnamed.
  • Do not rely on headings that describe styling rather than content.
<a class="skip-link" href="#main-content">Skip to main content</a>

<header>…</header>

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

<main id="main-content">…</main>

<aside aria-labelledby="related-title">
  <h2 id="related-title">Related resources</h2>
</aside>

<footer>…</footer>

06 · Forms

Separate the name, instructions, and error

A field label identifies the control. Help text explains constraints. An error explains what must be corrected.

Validation example

The error is connected with aria-describedby. Invalid state appears only after validation.

Native form
Use the address associated with your organization.
No validation result.
Name
Visible label associated through for and id.
Description
Help and error text are supplemental descriptions.
State
aria-invalid appears only after failure and is removed after correction.
Focus
Failure returns focus to the first invalid field.

07 · Failure modes

Common ways accessible interfaces regress

These patterns often look correct visually while exposing a broken accessibility model.

<div role="button"> by default

It recreates behavior the browser already implements. Use a native button.

Site navigation marked as menu

An ARIA menu promises a desktop command-menu keyboard model. Ordinary links should remain ordinary links.

Focusable content inside aria-hidden="true"

Keyboard focus can enter content that assistive technology cannot perceive.

Static ARIA state

A visual panel opens while aria-expanded remains false. State synchronization is part of the component contract.

Positive tabindex

Manual focus ordering becomes fragile as the DOM evolves. Use meaningful source order and roving focus only inside composite widgets.

Routine notices as alerts

role="alert" can interrupt current speech. Use status for ordinary confirmations and progress messages.

Grid semantics for a read-only table

A grid introduces two-dimensional focus and editing expectations. Use native table markup for tabular information.

08 · CSS foundation

Small reset, explicit rhythm, resilient layout

The reset removes inconsistent assumptions. The base and layout layers then restore intentional spacing, focus, overflow, and control geometry.

Included in the reset

  • Universal border-box sizing.
  • 100% text-size adjustment.
  • Explicit body and text-element margins.
  • List removal only for lists explicitly marked role="list".
  • Responsive block media.
  • Inherited form typography and color.

Explicitly excluded

  • appearance: none.
  • Global focus removal.
  • Global all: unset.
  • Unconditional smooth scrolling.
  • Global animation destruction.
  • Font-smoothing directives.
  • html { font-size: 62.5%; }.
  • Universal word breaking.
@layer reset {
  *, *::before, *::after {
    box-sizing: border-box;
  }

  html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    tab-size: 4;
  }

  body { margin: 0; }

  :where(h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd) {
    margin: 0;
  }

  :where(ul[role="list"], ol[role="list"]) {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  :where(button, input, select, textarea) {
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
  }

  ::file-selector-button { font: inherit; }

  :where(img, picture, video, canvas) {
    display: block;
    max-inline-size: 100%;
  }

  :where(img, video) { block-size: auto; }

  svg { max-inline-size: 100%; }
}
Layout recalibration applied.

This guide uses intrinsic auto-fit grids, min-inline-size: 0, bounded horizontal scrolling for tables and code, safe-area padding, 44-pixel controls, explicit square-button geometry, and one sticky header on mobile.

09 · Delivery gate

Component accessibility checklist

Progress is stored locally in this browser. Use the checklist as a pull-request and design-review contract.

The component begins with the most appropriate HTML element.

Visible text, labels, and accessible names describe the same user task.

Visual, DOM, ARIA, and application state remain synchronized.

Tab, Enter, Space, Escape, Arrow, Home, and End behavior match the role.

Focus entry, movement, visibility, containment, and return are intentional.

Content remains usable at 200% text resize and a 320 CSS-pixel viewport.

Text, boundaries, states, and focus remain perceptible without relying on color alone.

The accessibility tree, announcements, labels, role, value, and state are verified.

0 of 8 checks complete.

10 · Validation strategy

Automate detection, not judgment

Automation catches structural defects. Human testing verifies whether the experience is coherent and operable.

Static checks

  • HTML conformance.
  • Unsupported ARIA attributes.
  • Invalid role ownership.
  • Duplicate IDs.
  • Missing accessible names.

Browser checks

  • Keyboard-only operation.
  • Visible and unobscured focus.
  • Zoom and narrow reflow.
  • Reduced motion.
  • Forced colors and contrast.

Assistive technology

  • VoiceOver with Safari.
  • NVDA with Firefox or Chrome.
  • JAWS where enterprise support requires it.
  • Voice control for visible label alignment.

Evidence record

  • Operating system and version.
  • Browser and version.
  • Assistive technology and version.
  • Input method and viewport.
  • Pass, failure, notes, and reproduction.
Recommended CI sequence
HTML conformance
  ↓
Static accessibility linting
  ↓
axe-core component tests
  ↓
Browser keyboard tests
  ↓
Focus and state assertions
  ↓
Manual assistive-technology testing
When a component requires dedicated review

Require specialized accessibility review for comboboxes, listboxes, menus, trees, grids, rich-text editors, carousels, command palettes, drag-and-drop editors, and interactive canvas or diagram experiences.

11 · Standards

Primary references

The guide uses current W3C recommendations as the production baseline and treats working drafts as horizon signals.

ARIA in HTML

Defines valid role and aria-* usage on HTML elements. W3C Recommendation published April 15, 2026.

WAI-ARIA 1.2

Production role, state, property, and accessibility API mapping model.

WCAG 2.2

Product-level accessibility requirements, including focus, target size, dragging alternatives, reflow, and status messages.

Reduced motion

Platform preference detection for reducing or replacing non-essential animation.

Review component contract

Confirm semantics before implementation details.