What must be correct
- ARIA in HTML authoring conformance.
- WAI-ARIA 1.2 roles, states, and properties.
- WCAG 2.2 as the product acceptance target.
Enterprise implementation standard
Start with the user task and native HTML. Add only missing semantics. Verify keyboard, focus, state, and assistive-technology behavior.
01 · Standards baseline
Conformance, implementation guidance, browser mappings, and interoperability evidence answer different questions. Treating them as interchangeable creates false assurance.
APG is informative, not a conformance standard or production design system.
Support tables guide test priority. They do not replace product testing.
Track for roadmap planning. Do not silently promote drafts into the production baseline.
Ship against WCAG 2.2 and ARIA 1.2 conformance. Use APG to define interaction contracts. Use HTML-AAM and ARIA-AT to understand exposure and test risk. Track ARIA 1.3 separately until it advances beyond Working Draft.
The June 2026 Working Draft includes additions such as comment, suggestion, and mark roles, plus properties such as aria-description. These are useful roadmap signals for collaborative editing and richer description models, but draft status and interoperability evidence must remain explicit.
Prefer existing native and ARIA 1.2 patterns until browser, accessibility API, assistive-technology, and authoring-rule support is demonstrated for the target environment.
02 · Decision model
Follow this sequence for every interactive component. A visual design should not determine the role.
Is the user navigating, submitting, selecting, toggling, expanding, editing, or issuing an application command?
Prefer button, a, input, select, details, dialog, and table.
Add only the missing name, state, relationship, live announcement, or custom-widget role.
Match keyboard navigation, focus movement, activation, cancellation, selection, and disabled behavior.
The visual state, DOM state, ARIA state, and application state must describe the same condition.
Inspect keyboard operation, focus order, announcements, zoom, reflow, contrast, and real assistive technology.
role="button" promises button behavior. It does not create Enter or Space activation, focusability, disabled behavior, or form semantics.
03 · Name contract
The name must remain perceivable, stable, localizable, and aligned with visible text. Descriptions supplement the name. They do not repair a missing label.
Button text, link text, heading text.
label, legend, caption, alt.
aria-labelledbyReferences visible text already present in the interface.
aria-labelUse when a visible label is not practical, such as an icon-only control.
If visible text says “Send” but the accessible name begins with “Submit application,” speech users may not be able to activate the control by its visible label.
This simplified authoring check detects visible-label divergence. It does not reproduce the full Accessible Name and Description Computation algorithm.
04 · Role cost catalog
Search by role, native equivalent, required behavior, category, or review tier. High-cost composite widgets require centralized ownership and assistive-technology evidence.
Showing all roles.
| Role | Category | Native first | Use when | Primary obligation | Review tier |
|---|---|---|---|---|---|
button |
Widget | <button> |
A non-native element must act as a button. | Focus, Enter and Space activation, disabled behavior. | Component review |
checkbox |
Widget | <input type="checkbox"> |
A custom binary or tri-state selection is unavoidable. | aria-checked, Space activation, label, focus. |
Component review |
radio |
Widget | <input type="radio"> |
A custom mutually exclusive option is unavoidable. | Group semantics, checked state, arrow-key model. | Component review |
switch |
Widget | Checkbox or button | The binary state is explicitly understood as on or off. | aria-checked, stable label, immediate state change. |
Component review |
slider |
Widget | <input type="range"> |
A custom continuous-value control is essential. | Arrow/Home/End keys, min/max/current value, orientation. | Specialist review |
tablist |
Composite | Buttons may be sufficient | Mutually exclusive panels share one local context. | Roving focus, arrow keys, selection and panel linkage. | Specialist review |
menu |
Composite | Disclosure plus links | An application command menu behaves like desktop software. | Managed focus, arrow keys, Escape, type-ahead. | Specialist review |
listbox |
Composite | <select> |
Native select cannot meet the interaction requirement. | Managed focus, selection, type-ahead, option ownership. | Specialist review |
combobox |
Composite | Input plus datalist/select | An editable or selectable popup requires custom behavior. | Popup state, focus strategy, active option, keyboard model. | Specialist review |
grid |
Composite | <table> |
Cells are interactive like a spreadsheet. | Two-dimensional focus, row/cell semantics, edit mode. | Specialist review |
main |
Landmark | <main> |
Normally implicit through native HTML. | One primary main landmark per rendered page. | Native preferred |
navigation |
Landmark | <nav> |
Identify a significant navigation group. | Distinct labels when multiple navigation landmarks exist. | Native preferred |
search |
Landmark | <search> or labelled form |
Identify site or application search. | Clear landmark name when multiple search regions exist. | Native preferred |
region |
Landmark | Named <section> |
Content is a significant navigation destination. | Accessible name and restraint to avoid landmark overload. | Component review |
heading |
Structure | <h1>–<h6> |
Usually only for environments without native headings. | Correct level and document outline. | Native preferred |
list |
Structure | <ul> or <ol> |
Native list markup is unavailable. | Correct list-item ownership and meaningful grouping. | Native preferred |
status |
Live region | No direct equivalent | Routine dynamic information should be announced politely. | Update an existing region; do not move focus. | Component review |
alert |
Live region | No direct equivalent | An urgent condition requires immediate awareness. | Use sparingly; avoid interrupting routine work. | Component review |
dialog |
Window | <dialog> |
A focused task appears in a separate window context. | Name, initial focus, containment, Escape, focus return. | Component review |
alertdialog |
Window | <dialog> |
A brief urgent decision requires immediate response. | Concise message, explicit choices, disciplined focus. | Specialist review |
command |
Abstract | Never author directly | Only defines the ARIA ontology. | Do not use abstract roles in content. | Do not author |
05 · State model
Roles answer “what is this?” These attributes communicate identity, condition, and connection.
| 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. |
checked plus aria-checked="false" creates an invalid state model. Native HTML state takes priority.
06 · Focus architecture
Keyboard focus, visual selection, virtual cursor position, and application state are related but not interchangeable. Composite widgets fail when those states drift.
| Model | Use for | Core invariant | Primary risk |
|---|---|---|---|
| Native DOM focus | Forms, disclosures, ordinary buttons and links. | Source order matches reading and interaction order. | CSS reordering or hidden overlays obscure the active control. |
Roving tabindex | Tabs, toolbars, radio groups, menus, trees. | Exactly one managed child is in the sequential Tab order. | Two active Tab stops, stale selection, or focus loss after DOM updates. |
aria-activedescendant | Comboboxes and large composites where DOM focus stays on a container. | The active descendant exists, is owned correctly, and remains perceptible. | Visual focus and announced focus diverge. |
| Modal focus scope | Dialogs and blocking workflows. | Initial focus is intentional; background is inert; focus returns logically. | Focus enters hidden content or returns to a removed invoker. |
| SPA route focus | Client-side navigation and major view changes. | Title, history, focus, and announcement describe the new view. | Content changes visually while screen-reader context remains in the prior view. |
Sticky headers, drawers, banners, and virtual keyboards must not entirely hide the focused component. Test at zoom and narrow viewports, not only at the default desktop canvas.
07 · Native primitives
Use platform behavior where it fits. Native behavior still requires clear naming, intentional focus, and product-level interoperability testing.
<details> + <summary>Built-in toggle, focusability, keyboard activation, and expanded-state exposure.
Do not overridesummary with role="button".<dialog>showModal() creates a modal top-layer context and makes the rest of the document inert.
popoverProvides show/hide, light dismiss, top-layer rendering, and declarative invokers.
Popover behavior does not automatically supply dialog, menu, or tooltip semantics.inertInert content is generally not focusable and is not exposed through accessibility APIs.
Use for temporarily unavailable subtrees, not as a substitute for disabled control semantics.hiddenUse when content should not participate in layout, interaction, or the accessibility tree.
Do not pair with redundantaria-hidden="true".aria-hiddenUseful for decorative duplicates that remain visually rendered.
Never apply to focusable content or an ancestor of visible interactive descendants.The popover supplies lifecycle behavior. The explicit dialog role and name describe the content purpose.
Choose semantics based on the content and interaction. A menu, tooltip, listbox, or dialog still needs its own contract.
08 · Runnable patterns
These examples are deliberately small. Each demonstrates the semantic baseline, state owner, keyboard behavior, and focus strategy.
Use for ordinary website navigation. Do not convert a group of links into an application menu.
aria-expanded on the button mirrors hidden on the panel.<button
type="button"
aria-expanded="false"
aria-controls="resources-panel"
>
Resources
</button>
<div id="resources-panel" hidden>
<a href="/guides">Guides</a>
</div>
Use only for mutually exclusive panels. A row of content filters is not automatically a tab interface.
tablist owns tab elements; each tab controls a tabpanel.aria-selected="true"; inactive tabs use tabindex="-1".Native dialog provides the window primitive. The application still owns naming, focus placement, cancellation, and return.
<dialog> opened with showModal().aria-labelledby references the visible heading.Routine updates should be announced without moving focus or interrupting the user.
status supplies polite live-region behavior.Use when the product language clearly describes an immediate on/off setting. A native checkbox is still the safer default.
Setting is off.
aria-checked changes; the visible label remains stable.09 · Component contract
A reusable component is not complete until semantics, naming, state, keyboard, focus, announcements, fallback, testing, and operational ownership are explicit.
Generated review contract
type ReviewTier = "native" | "component" | "specialist";
type AccessibilityContract = {
component: string;
userTask: string;
nativeFoundation: string;
role: string | "implicit";
nameSource: string;
states: readonly string[];
relationships: readonly string[];
keyboard: readonly string[];
focus: {
entry: string;
movement: string;
return: string;
};
announcements: readonly string[];
fallback: string;
testMatrix: readonly string[];
owner: string;
reviewTier: ReviewTier;
};10 · Page structure
Landmarks are navigation destinations, not visual containers. Too many named regions produce a noisy, flat page map.
<main>.<nav>.role="main" to <main>.<nav> for every list of links.<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>
11 · Forms
A field label identifies the control. Help text explains constraints. An error explains what must be corrected.
The error is connected with aria-describedby. Invalid state appears only after validation.
label associated through for and id.aria-invalid appears only after failure and is removed after correction.12 · Failure modes
These patterns often look correct visually while exposing a broken accessibility model.
<div role="button"> by defaultIt recreates behavior the browser already implements. Use a native button.
menuAn ARIA menu promises a desktop command-menu keyboard model. Ordinary links should remain ordinary links.
aria-hidden="true"Keyboard focus can enter content that assistive technology cannot perceive.
A visual panel opens while aria-expanded remains false. State synchronization is part of the component contract.
tabindexManual focus ordering becomes fragile as the DOM evolves. Use meaningful source order and roving focus only inside composite widgets.
role="alert" can interrupt current speech. Use status for ordinary confirmations and progress messages.
A grid introduces two-dimensional focus and editing expectations. Use native table markup for tabular information.
13 · Validation strategy
Automation catches structural defects. Human testing verifies whether the experience is coherent and operable.
HTML conformance
↓
Static accessibility linting
↓
axe-core component tests
↓
Browser keyboard tests
↓
Focus and state assertions
↓
Manual assistive-technology testing
| Assertion | Detects | Still requires human review |
|---|---|---|
| Role value is valid | Unknown or abstract authored roles. | Whether the role matches the user task. |
| ARIA attribute is defined and permitted | Typos and unsupported role/attribute combinations. | Whether the attribute communicates useful state. |
| Required states and properties exist | Incomplete custom-widget semantics. | State synchronization during every transition. |
| Accessible name is non-empty | Unnamed controls, links, fields, and images. | Name quality, visible-label alignment, and localization. |
| Hidden content is not focusable | aria-hidden conflicts with sequential focus. | Focus recovery and off-screen interaction traps. |
| ID references resolve | Broken labels, descriptions, controls, and ownership. | Whether the relationship is conceptually correct. |
W3C advises teams to perform their own tests across the browser and assistive-technology combinations relevant to the target audience.
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.
14 · Enterprise considerations
Most production regressions occur at integration boundaries: routing, virtualization, permissions, loading, translation, design-system overrides, and cross-team ownership.
Update the document title and history. Move focus to a meaningful destination when the context changes. Announce asynchronous route completion without duplicating speech.
Use stable regions, aria-busy only while updating, and restrained status announcements. Avoid re-announcing the entire surface for incremental updates.
Preserve logical position, focus, selection, and row or set metadata. Never remove the actively focused item without a deterministic recovery path.
Localize visible and accessible names together. Mark language changes. Test expansion, pronunciation, bidirectional layouts, and keyboard conventions.
Distinguish unavailable, hidden, read-only, and disabled. Native disabled changes interaction; aria-disabled only communicates state and requires behavioral enforcement.
Define semantics at the component boundary. Verify label and relationship behavior across shadow roots, browser mappings, and framework hydration.
Track keyboard abandonment, validation loops, focus loss, repeated errors, and inaccessible fallbacks without collecting assistive-technology identity as a proxy for disability.
Centralize high-cost composite widgets. Version their contracts, support matrix, evidence, known limitations, and deprecation path.
15 · CSS foundation
The reset removes inconsistent assumptions. The base and layout layers then restore intentional spacing, focus, overflow, and control geometry.
border-box sizing.role="list".appearance: none.all: unset.html { font-size: 62.5%; }.@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%; }
}
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.
16 · Delivery gate
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.
Core content remains readable without JavaScript. Storage denial, loading failure, and unsupported enhancement paths recover clearly.
Browser, operating system, assistive technology, input method, viewport, result, and reproduction evidence are attached to the release record.
17 · Standards and provenance
Claims are separated by authority: normative production standards, informative implementation guidance, mapping drafts, and interoperability evidence.
Author conformance requirements for using WAI-ARIA 1.2 attributes on HTML elements.
Production role, state, property, and semantic model.
Product-level conformance target. Includes focus not obscured, dragging alternatives, target size, redundant entry, and accessible authentication.
Keyboard, focus, naming, landmark, and widget-pattern guidance. Not a normative standard or production design system.
Explains why incorrect ARIA can misrepresent the non-visual experience and why native semantics are preferred.
Native-first authoring rules, keyboard obligations, and prohibitions on hiding focusable content.
Horizon specification. Track changes separately from the production baseline.
Defines how user agents expose HTML semantics through platform accessibility APIs.
Guides test prioritization. W3C explicitly advises product teams to perform their own testing.
Defines top-layer, focus, toggle, and restoration behavior. Popover on a semantic-neutral element still needs appropriate semantics.
Automatable assertions for valid roles, attributes, required states, accessible names, and focusable hidden content.
Combines automated checks with knowledgeable human and assistive-technology evaluation.
Prepared for the document owner with AI-assisted research and implementation. Linked standards remain the source of truth.