a11y teacher edition W3C WCAG 2.2 & WCAG 3.0 draft reference
Plain English Accessibility Hub

Translating W3C Standards for Designers, Developers, QA & Product teams

The First Rule of ARIA

"If you can use a native HTML element or attribute with the semantics and behavior you require already built in, then do so." — W3C ARIA Authoring Practices Guide & Using ARIA in HTML
Native Preferred: HTML provides a built-in element (e.g. <dialog>, <details>, <meter>, <input type="range">). Use native HTML first.
Hybrid Enhancement: Semantic HTML structure combined with targeted ARIA (e.g. <nav> + aria-current="page", Popover API, indeterminate checkboxes).
ARIA Required: No native HTML element exists yet (e.g. tabs, treeview, toolbar). The APG pattern is required for full accessibility.
Category:
Verdict:
Showing 30 of 30 patterns
Ctrl+K to focus search • Tab to explore demos
Structure & Layout Native Element Preferred

Accordion

A vertically stacked set of interactive headings that each reveal a section of content. Modern HTML natively supports exclusive accordions with name="group" without JavaScript.

First Rule Analysis:

Under the First Rule of ARIA ("No ARIA is better than bad ARIA"), native <details> with <summary> is vastly superior for standard document and content disclosure. Modern browsers support exclusive accordions natively using the name attribute on multiple <details> tags (opening one closes the others). The APG ARIA pattern requires custom buttons, aria-expanded, aria-controls, role="region", and custom JavaScript keyboard event handlers.

Semantic Target: <details name="group"> + <summary>
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS

Name: Alex Rivera

Email: alex@example.com

Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Personal Details

Name: Alex Rivera

Email: alex@example.com

Billing Information

Payment: Invoiced Net 30

Billing Address: 100 Main St

Native exclusive group: name="demo-semantic-acc" (0 JS!)
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~40 lines (HTML + JS))

Requires manual state synchronization, event listeners, and attribute management on every toggle.

Wiring & Implementation Requirements:

  • Heading tag (e.g. <h3>) wrapping each trigger <button type="button">
  • aria-expanded="true/false" maintained via JavaScript on every click/keydown
  • aria-controls="panel-id" pointing to the unique ID of the expandable panel
  • Panel marked with role="region" and aria-labelledby="button-id"
  • Panel hidden attribute or CSS display:none synchronized with expanded state
  • Custom JavaScript event listeners for click and keyboard triggers

Keyboard Functionality:

  • Enter / Space: Toggles expanded/collapsed state via JavaScript listener
  • Tab / Shift+Tab: Moves focus sequentially between trigger buttons and open panel focusables
  • Arrow Down / Up: Moves focus across triggers (optional APG enhancement)

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "button, Billing Information, expanded [or collapsed], region Billing Information".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~6 lines of declarative HTML)

Built directly into the browser engine in C++. Completely functional with JavaScript disabled.

Wiring & Implementation Requirements:

  • Native <details> parent tag and <summary> heading element
  • name="group-name" attribute on each details element to enforce exclusive single-panel opening
  • 0 lines of JavaScript needed for toggling, state management, or exclusive accordion behavior

Keyboard Functionality:

  • Enter / Space: Natively toggles summary open/closed state
  • Tab / Shift+Tab: Natively navigates to next summary or active panel content

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces "details, collapsed [or expanded], Billing Information, summary" via browser accessibility tree.

Real-World Limitations of Native Semantic HTML (Accordion):

  • Default browser disclosure triangle marker requires ::marker or ::-webkit-details-marker CSS reset.
  • Historically difficult to animate height smoothly (now supported in modern browsers via interpolate-size: allow-keywords and @starting-style).
  • Heading hierarchy inside <summary> requires placing heading tags within summary (<summary><h3>Title</h3></summary>).
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<details name="group"> + <summary>)
/* Customizing Native <details> without default marker */
details {
  border: 1px solid var(--border-default);
  border-radius: 8px;
  overflow: hidden;
}
summary {
  list-style: none;
  padding: 12px 16px;
  cursor: pointer;
  font-weight: 600;
  display: flex;
  justify-content: space-between;
}
/* Remove WebKit legacy triangle */
summary::-webkit-details-marker { display: none; }
/* Custom animated chevron */
summary::after {
  content: "▼";
  transition: transform 0.2s ease;
}
details[open] summary::after {
  transform: rotate(180deg);
}
State Attribute CSS for ARIA
/* Styling ARIA Accordion via state attributes */
.accordion-trigger[aria-expanded="true"] .acc-icon {
  transform: rotate(180deg);
}
.accordion-panel[hidden] {
  display: none;
}
💡 Pro Styling Tips:
  • Use summary::-webkit-details-marker { display: none; } and list-style: none on summary to remove default arrows across all engines.
  • Target details[open] summary to change background or rotate custom indicator icons.
Dialogs & Overlays Native Element Preferred

Dialog (Modal)

A modal dialog overlays the main view and requires user interaction before returning. The native HTML <dialog> provides top-layer rendering, native focus trapping, Esc closing, and automatic backdrop styling.

First Rule Analysis:

Implementing an accessible modal dialog with ARIA from scratch is notoriously error-prone: you must manage a backdrop div, trap keyboard focus within the dialog, handle the Esc key, mark all background DOM nodes as inert or aria-hidden="true", and restore focus to the trigger on close. Native <dialog>.showModal() does ALL of this in the browser engine natively.

Semantic Target: <dialog> + showModal()
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features

Confirm Deletion (Native)

Rendered in browser Top Layer with native backdrop & focus trap.

Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Extreme Effort (~70-110 lines of complex JS + HTML)

Focus trap leaks and missing background inerting are among the most common web accessibility failures.

Wiring & Implementation Requirements:

  • Container element with role="dialog", aria-modal="true", and aria-labelledby="title-id"
  • Fixed viewport backdrop <div> element
  • JavaScript focus trap: intercepting Tab/Shift+Tab to keep focus within dialog focusable nodes
  • Marking all page siblings with inert or aria-hidden="true" while modal is open
  • JavaScript keydown listener for Escape key to close modal
  • Tracking opener button in document.activeElement and restoring focus upon close

Keyboard Functionality:

  • Tab / Shift+Tab: Trapped within dialog, cycling between first and last focusable element
  • Escape: Closes dialog and returns focus to opener button

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "dialog modal, Confirm Deletion". Assistive tech virtual reading cursor must be confined to dialog content.

🟢 Semantic HTML Equivalent Low (1-2 lines JS) (~5 lines of HTML + 1 line JS (dialog.showModal()))

Browser Top Layer handles z-index, backdrop, focus containment, and inertness natively.

Wiring & Implementation Requirements:

  • Native <dialog> element in HTML
  • Invoked via dialog.showModal()
  • Native ::backdrop pseudo-element for background dimming
  • Optional <form method="dialog"> to close modal natively on button click without JS

Keyboard Functionality:

  • Tab / Shift+Tab: Automatically trapped inside modal by browser engine
  • Escape: Natively fires cancel event, closes dialog, and restores focus to invoking element

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces native dialog role, title, and isolates reading order to the dialog natively.

Real-World Limitations of Native Semantic HTML (Dialog (Modal)):

  • Calling dialog.show() creates a non-modal dialog without focus trap or backdrop; dialog.showModal() must be used for modals.
  • Animating entry and exit transitions requires modern CSS (@starting-style and transition-behavior: allow-discrete).
  • Positioning relative to triggering element as a flyout requires CSS Anchor Positioning or manual offset calculation.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<dialog> + showModal())
/* Styling Native <dialog> and Backdrop */
dialog {
  border: none;
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
  max-width: 460px;
}
dialog::backdrop {
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(6px);
}
/* Modern smooth opening animation */
@starting-style {
  dialog[open] {
    opacity: 0;
    transform: scale(0.95);
  }
}
State Attribute CSS for ARIA
/* ARIA Dialog requires custom fixed overlay */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}
💡 Pro Styling Tips:
  • Always style dialog::backdrop directly rather than injecting custom backdrop divs.
  • Use method="dialog" on nested forms for zero-JS button dismissals.
Inputs & Controls Native Element Preferred

Switch

A toggle control representing a binary on/off state. Standard HTML checkbox supports role="switch" for exact AT announcement while preserving native form submission and keyboard interaction.

First Rule Analysis:

Developers often create custom <div> or <button> switches with ARIA, requiring manual click, spacebar, and enter handlers, plus custom state tracking. Using a native <input type="checkbox" role="switch"> leverages native checkbox form submission, native keyboard behavior, and native assistive technology support while announcing itself as a switch.

Semantic Target: <input type="checkbox" role="switch">
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~25 lines of HTML, CSS & JS)

Requires custom state tracking and hidden form inputs for form integration.

Wiring & Implementation Requirements:

  • <button type="button" role="switch" aria-checked="false"> or <div role="switch" tabindex="0">
  • JavaScript click and keydown (Space/Enter) handlers
  • Updating aria-checked="true/false" attribute dynamically
  • Does NOT submit in standard HTML <form> without hidden input

Keyboard Functionality:

  • Space: Toggles switch state between true and false
  • Enter: Toggles switch in button context
  • Tab: Moves focus to the switch

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "switch, Notifications, on [or off]".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~4 lines of HTML + CSS)

Native checkbox behavior with switch role announcement.

Wiring & Implementation Requirements:

  • <input type="checkbox" role="switch"> inside a <label>
  • 0 lines of JavaScript needed
  • Submits natively in HTML forms (submits name=on when checked)

Keyboard Functionality:

  • Space: Natively toggles checked state
  • Tab: Focuses native checkbox

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces "switch, Notifications, checked [or not checked]".

Real-World Limitations of Native Semantic HTML (Switch):

  • Browsers render <input type="checkbox" role="switch"> as a standard square checkbox unless styled with CSS appearance: none.
  • Form submission sends the value only when checked (standard checkbox behavior).
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<input type="checkbox" role="switch">)
/* Styling Native Checkbox into a Sliding Switch */
input[type="checkbox"][role="switch"] {
  appearance: none;
  width: 44px;
  height: 24px;
  background: #334155;
  border-radius: 999px;
  position: relative;
  cursor: pointer;
  transition: background-color 0.2s;
}
input[type="checkbox"][role="switch"]::before {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  top: 3px; left: 3px;
  background: #ffffff;
  transition: transform 0.2s;
}
input[type="checkbox"][role="switch"]:checked {
  background: #059669;
}
input[type="checkbox"][role="switch"]:checked::before {
  transform: translateX(20px);
}
State Attribute CSS for ARIA
button[role="switch"][aria-checked="true"] .switch-track {
  background: #a855f7;
}
button[role="switch"][aria-checked="true"] .switch-thumb {
  transform: translateX(20px);
}
💡 Pro Styling Tips:
  • Use appearance: none directly on the input[type="checkbox"][role="switch"] to avoid extra span wrapper markup while keeping full focus visibility intact.
Inputs & Controls Native Element Preferred

Slider

A user input where the user sets a value from a given range. Native <input type="range"> provides full keyboard, mouse, touch, and screen reader support without JavaScript.

First Rule Analysis:

The APG ARIA slider requires building custom track and thumb markup, managing aria-valuenow, aria-valuemin, aria-valuemax, tracking mouse dragging, touch movements, and listening for ArrowLeft, ArrowRight, ArrowUp, ArrowDown, PageUp, PageDown, Home, and End keys. Native <input type="range"> provides all of this out of the box with zero JavaScript.

Semantic Target: <input type="range">
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Use ← → Arrow keys or Home/End
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Native keyboard, mouse, touch & form integration
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~80-120 lines of JS + math + CSS)

Requires touch, mouse, pointer, and keyboard coordinate math and bounding box calculations.

Wiring & Implementation Requirements:

  • <div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50">
  • Custom track element and draggable handle element
  • Mouse drag listener, Touch move listener, pointer capture
  • Keydown listener for ArrowLeft, ArrowRight, ArrowUp, ArrowDown, PageUp, PageDown, Home, End
  • Does not participate in HTML form submit without hidden input

Keyboard Functionality:

  • Arrow Left / Down: Decrements value by step
  • Arrow Right / Up: Increments value by step
  • Page Up / Down: Increments / decrements by large step (e.g. 10)
  • Home / End: Jumps to minimum / maximum values

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "slider, Volume, 50%, min 0, max 100". Updates on every step.

🟢 Semantic HTML Equivalent Minimal (0 JS) (~2 lines of HTML + CSS)

Complete accessibility, keyboard, touch swipe, and mouse drag built into the browser engine.

Wiring & Implementation Requirements:

  • <input type="range" min="0" max="100" value="50">
  • Built-in <output> element for live visual value display
  • 0 lines of JavaScript needed for slider operation

Keyboard Functionality:

  • Natively supports all arrow keys, PageUp, PageDown, Home, and End without a single line of JS.

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces range slider, current value, min, max, and orientation.

Real-World Limitations of Native Semantic HTML (Slider):

  • Cross-browser thumb and track styling requires two separate vendor prefixes (::-webkit-slider-thumb and ::-moz-range-thumb).
  • Dual-fill track styling (highlighting the completed portion of the track) is not natively standardized and requires CSS linear-gradient or accent-color.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<input type="range">)
/* Styling Native Range Input */
input[type="range"] {
  accent-color: #059669; /* Easiest modern styling */
  width: 100%;
}
/* Advanced Cross-Browser Custom Thumb */
input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #059669;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}
input[type="range"]::-moz-range-thumb {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #059669;
  border: none;
}
State Attribute CSS for ARIA
.slider-handle {
  position: absolute;
  left: var(--percent);
  transform: translate(-50%, -50%);
}
💡 Pro Styling Tips:
  • accent-color: #color is supported in all modern browsers and styles the native slider thumb and filled track with 1 line of CSS!
Inputs & Controls Native Element Preferred

Meter

A graphical display of a numeric value within a known range, such as disk usage or battery level. The native HTML <meter> element includes semantic understanding of optimum, low, and high thresholds.

First Rule Analysis:

The native <meter> element communicates scalar measurement and gauge semantics directly to assistive technologies. It also provides built-in attributes for min, max, low, high, and optimum, allowing browsers and user agents to convey whether a gauge is in a favorable or alert status. The ARIA role="meter" requires custom styling, manual aria-valuenow updates, and cannot natively represent the optimum range concept.

Semantic Target: <meter>
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Storage Usage: 72%
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
72%
72%
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~20 lines of HTML, CSS & JS)

Must manually compute percentages, fill widths, and color thresholds.

Wiring & Implementation Requirements:

  • <div role="meter" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" aria-label="...">
  • Custom track container + custom fill <div> with inline style="width: 70%"
  • Manual color updating logic in JS to change colors if value enters warning/critical zones

Keyboard Functionality:

  • Not focusable (read-only scalar display)

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "meter, Disk Usage, 70 percent".

🟢 Semantic HTML Equivalent Minimal (0 JS) (1 line of HTML)

Native browser scalar gauge with built-in optimum heuristics.

Wiring & Implementation Requirements:

  • <meter min="0" max="100" low="33" high="66" optimum="80" value="70">70%</meter>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Read-only native element; skipped by Tab sequence

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces meter value and whether reading is optimum, suboptimal, or alert.

Real-World Limitations of Native Semantic HTML (Meter):

  • Browser default styling renders native OS appearance, which looks drastically different between Windows, macOS, and Linux.
  • Custom styling requires resetting -webkit-appearance and targeting vendor pseudo-elements (::-webkit-meter-bar, ::-webkit-meter-optimum-value).
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<meter>)
/* Customizing Native <meter> */
meter {
  width: 100%;
  height: 16px;
  border-radius: 999px;
  overflow: hidden;
}
meter::-webkit-meter-bar {
  background: #1e293b;
  border: 1px solid rgba(255,255,255,0.1);
}
meter::-webkit-meter-optimum-value {
  background: linear-gradient(90deg, #38bdf8, #34d399);
}
State Attribute CSS for ARIA
.meter-bar { width: calc(var(--val) * 1%); background: #a855f7; }
💡 Pro Styling Tips:
  • Include fallback text inside the <meter> tag (<meter value="70">70%</meter>) for older user agents.
Inputs & Controls Native Element Preferred

Button

The primary interactive control for triggering actions. The classic demonstration of the First Rule of ARIA: a <div> with role="button" requires extensive custom JavaScript to replicate native <button>.

First Rule Analysis:

A native <button> element comes with automatic keyboard activation (both Space and Enter fire click), native focusability, native disabled state (which prevents click and keyboard events), form integration (type="submit", type="reset"), and standard accessibility API mapping. An ARIA fake button (<div role="button" tabindex="0">) requires manual keydown listeners for Space and Enter, custom disabled management, and often fails in screen reader virtual cursor modes.

Semantic Target: <button type="button">
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Custom <div role="button">
Activated: 0 times
Requires manual Space & Enter keydown JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Activated: 0 times
Native Space & Enter click, disabled state, form submit
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~30 lines of JS + CSS to duplicate native button)

Common source of bugs where Space key causes page scroll or disabled buttons still trigger.

Wiring & Implementation Requirements:

  • <div role="button" tabindex="0">
  • Keydown listener for Enter to invoke action
  • Keydown listener for Space to call e.preventDefault() (prevent page scroll) and invoke action on keyup
  • Manual :focus-visible styling
  • Manual disabled state management (aria-disabled="true" and tabindex="-1")
  • Does NOT submit forms without manual form submission JS

Keyboard Functionality:

  • Enter: Triggers button action
  • Space: Triggers button action (must prevent window scroll)

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "button, Save Changes".

🟢 Semantic HTML Equivalent Minimal (0 JS) (1 line of HTML)

The epitome of the First Rule of ARIA.

Wiring & Implementation Requirements:

  • <button type="button">Save Changes</button>
  • 0 lines of helper code

Keyboard Functionality:

  • Enter and Space natively trigger click event without scrolling
  • Disabled attribute prevents all focus and click events automatically

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces button role and accessible name.

Real-World Limitations of Native Semantic HTML (Button):

  • Default browser button styling has legacy borders and backgrounds; requires standard CSS reset (border: none; background: transparent; font: inherit).
  • Buttons default to type="submit" inside a <form> if type attribute is omitted.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<button type="button">)
/* Modern Reset & Styled Button */
button {
  all: unset;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 20px;
  background: #0284c7;
  color: #fff;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
}
button:focus-visible {
  outline: 3px solid #38bdf8;
  outline-offset: 3px;
}
State Attribute CSS for ARIA
div[role="button"]:focus-visible { outline: 3px solid #a855f7; }
💡 Pro Styling Tips:
  • Always specify type="button" on non-submitting buttons to prevent accidental form submissions!
Inputs & Controls Native Element Preferred

Radio Group

A set of checkable buttons where no more than one button can be checked simultaneously. Native radio buttons provide single tab-stop roving focus and arrow navigation natively.

First Rule Analysis:

The APG ARIA radio group pattern requires manually implementing roving tabindex (managing tabindex="0" on the selected radio and tabindex="-1" on all others), listening for ArrowUp, ArrowDown, ArrowLeft, ArrowRight, and updating aria-checked. Native <input type="radio" name="..."> grouped by a <fieldset> with <legend> provides this entire behavior natively with zero JavaScript.

Semantic Target: <fieldset> + <legend> + <input type="radio">
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Shipping Speed:
Navigate with ↑ ↓ or ← → keys
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Shipping Speed:
Arrow navigation & roving focus built-in
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~50 lines of JS + CSS)

Must manually implement roving focus and keyboard traversal that HTML does natively.

Wiring & Implementation Requirements:

  • <div role="radiogroup" aria-labelledby="title-id">
  • <div role="radio" tabindex="0/-1" aria-checked="true/false">
  • Roving tabindex algorithm across all 4 arrow keys
  • Manual state sync and focus setting in JS

Keyboard Functionality:

  • Arrow Up / Down / Left / Right: Moves focus and checks selected radio
  • Tab: Moves focus to the checked radio button (single tab stop)

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "radio button, checked 1 of 3, Shipping Speed".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~6 lines of HTML)

Native browser implementation.

Wiring & Implementation Requirements:

  • <fieldset><legend>Title</legend><label><input type="radio" name="grp" value="..."> ...</label></fieldset>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Natively provides single tab stop for group and arrow key selection across all browsers.

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces legend as group context, then radio button label, state, and position (1 of 3).

Real-World Limitations of Native Semantic HTML (Radio Group):

  • Default browser radio circles have rigid OS styling unless overridden with accent-color or appearance: none.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<fieldset> + <legend> + <input type="radio">)
/* Modern Native Radio Styling */
input[type="radio"] {
  accent-color: #059669;
  width: 18px;
  height: 18px;
  cursor: pointer;
}
State Attribute CSS for ARIA
[role="radio"][aria-checked="true"] .radio-dot { background: #a855f7; }
💡 Pro Styling Tips:
  • Always wrap native radio groups in <fieldset> with <legend> so screen reader users hear the group prompt before the option.
Inputs & Controls Hybrid Enhancement

Checkbox (Tri-State / Mixed)

A control that allows the user to toggle between checked, unchecked, or partially checked (mixed/indeterminate) states. Native checkbox handles the mixed state via the DOM indeterminate property.

First Rule Analysis:

While creating a custom checkbox (<div role="checkbox">) requires writing custom Space key listeners and focus styling, the native <input type="checkbox"> handles focus, toggling, and form submission natively. For parent "select all" checkboxes that need a mixed state, setting the DOM property checkbox.indeterminate = true provides native screen reader mixed state announcements without abandoning native checkbox semantics.

Semantic Target: <input type="checkbox"> + indeterminate property
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Press Space to toggle checked / unchecked / mixed
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Native Space toggle & native indeterminate property
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~30 lines of JS + CSS)

Manual rendering of tri-state icons and keyboard space listeners.

Wiring & Implementation Requirements:

  • <div role="checkbox" tabindex="0" aria-checked="mixed">
  • Custom SVG or font icon for checkmark and minus icon
  • JavaScript Space key listener to cycle between false -> true -> mixed

Keyboard Functionality:

  • Space: Cycles between checked, unchecked, and mixed

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "checkbox, partially checked [mixed], All Permissions".

🟢 Semantic HTML Equivalent Low (1-2 lines JS) (1 line JS: el.indeterminate = true)

Leverages native OS tri-state rendering and accessibility tree states.

Wiring & Implementation Requirements:

  • Native <input type="checkbox">
  • JavaScript setting checkbox.indeterminate = true for parent status

Keyboard Functionality:

  • Space: Natively checks or unchecks checkbox

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces "checkbox, partially checked / mixed".

Real-World Limitations of Native Semantic HTML (Checkbox (Tri-State / Mixed)):

  • The indeterminate state CANNOT be set via HTML markup alone (e.g. there is no indeterminate HTML attribute); it MUST be set via JavaScript property: input.indeterminate = true.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<input type="checkbox"> + indeterminate property)
/* Styling Native Checkbox & Indeterminate State */
input[type="checkbox"]:indeterminate {
  accent-color: #7c3aed;
}
State Attribute CSS for ARIA
[role="checkbox"][aria-checked="mixed"] .custom-box { background: #7c3aed; }
💡 Pro Styling Tips:
  • Use the :indeterminate CSS pseudo-class to style parent checkboxes when in the mixed state.
Structure & Layout Native Element Preferred

Disclosure (Show/Hide)

A simple button that controls the visibility of an associated section of content. Modern HTML <details> and <summary> provide this natively with zero JavaScript.

First Rule Analysis:

The disclosure pattern is one of the most common web interactions. Before HTML5 <details>, developers used <button aria-expanded="false" aria-controls="content">. Native <details> provides complete keyboard accessibility, automatic aria-expanded state handling, built-in search-on-page text matching (browsers automatically expand details when searching with Ctrl+F), and zero JavaScript overhead.

Semantic Target: <details> + <summary>
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Show Details (Semantic <details>)

Disclosed content revealed natively with built-in browser Find (Ctrl+F) expansion.

Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~20 lines of HTML + JS)

Requires synchronizing aria-expanded attribute with panel hidden state.

Wiring & Implementation Requirements:

  • <button type="button" aria-expanded="false" aria-controls="content-id">
  • <div id="content-id" hidden>
  • Click event listener to flip aria-expanded and hidden

Keyboard Functionality:

  • Enter / Space: Toggles expanded/collapsed state via JS

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "button, collapsed [or expanded], What is WCAG 3.0?".

🟢 Semantic HTML Equivalent Minimal (0 JS) (3 lines of HTML)

Standard HTML5 disclosure.

Wiring & Implementation Requirements:

  • <details><summary>Title</summary><p>Content</p></details>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Enter / Space: Natively toggles details open state

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces "details, collapsed [or expanded]".

Real-World Limitations of Native Semantic HTML (Disclosure (Show/Hide)):

  • Browsers render default black triangle arrow that requires removal via CSS.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<details> + <summary>)
details summary {
  list-style: none;
  cursor: pointer;
  padding: 8px 12px;
}
details summary::-webkit-details-marker {
  display: none;
}
State Attribute CSS for ARIA
button[aria-expanded="true"] + div { display: block; }
💡 Pro Styling Tips:
  • Details contents automatically expand when users search with browser Find (Ctrl+F)!
Inputs & Controls Native Preferred for Basic; ARIA for Rich Popups

Combobox / Autocomplete

A composite widget combining a single-line textbox with an associated popup listbox. Native <datalist> provides zero-JS autocomplete, while APG Combobox is needed for rich custom dropdowns.

First Rule Analysis:

For standard text suggestion and search autocomplete, the native HTML <datalist> element paired with an <input list="..."> provides built-in keyboard navigation, native OS suggestions, and screen reader announcements with zero JavaScript. The APG Combobox pattern is only warranted when dropdown options require rich HTML markup (avatars, subheadings, badges) or multi-select chip tags.

Semantic Target: <input list="..."> + <datalist>
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Native <datalist> autocomplete with 0 JavaScript
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Extreme Effort (~120-180 lines of JS + HTML)

Requires intricate keyboard focus management, virtual cursor tracking, and ARIA syncing.

Wiring & Implementation Requirements:

  • <input role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="list-id">
  • <ul role="listbox" id="list-id"> with <li role="option">
  • Managing aria-activedescendant or roving tabindex
  • Listening for ArrowDown, ArrowUp, Enter, Escape, Home, End
  • Filtering list items dynamically on text input

Keyboard Functionality:

  • Arrow Down: Opens popup list and moves active descendant
  • Enter: Selects active option and closes list
  • Escape: Closes popup listbox and keeps input focus

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "combobox, expanded / collapsed, option 1 of 5".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~6 lines of HTML)

Zero-JS native autocomplete provided by browser.

Wiring & Implementation Requirements:

  • <input list="items-id"> + <datalist id="items-id"><option value="...">...</datalist>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Arrow Down: Natively opens suggestion dropdown
  • Enter: Selects highlighted suggestion

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces available suggestions and input auto-complete.

Real-World Limitations of Native Semantic HTML (Combobox / Autocomplete):

  • Option items in <datalist> CANNOT be styled with custom CSS or contain rich HTML (avatars, icons, secondary descriptions, badges).
  • Dropdown presentation is controlled entirely by the operating system / browser UI.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<input list="..."> + <datalist>)
/* Styling the Input with Datalist */
input[list] {
  padding: 10px 14px;
  border: 1px solid var(--border-default);
  border-radius: 8px;
  background: var(--surface-card);
  color: var(--text-primary);
}
State Attribute CSS for ARIA
.cb-listbox { position: absolute; background: #1c1b1f; border: 1px solid #a855f7; }
💡 Pro Styling Tips:
  • When simple string autocomplete is needed, use <datalist>. Switch to the APG Combobox pattern ONLY when options require rich media or multi-column layouts.
Dialogs & Overlays Native Popover API Preferred for Navigation

Menu Button / Popover

A button that opens a flyout menu. The APG Menu pattern is designed for desktop-style application command actions; for site navigation, the modern HTML Popover API is preferred.

First Rule Analysis:

One of the most widespread accessibility anti-patterns on the web is using ARIA role="menu" and role="menuitem" for site navigation links. In ARIA, a menu is an application menu (like File/Edit in a desktop app) where Tab exits the menu and Arrow keys navigate items. When applied to website dropdowns, screen reader users expect arrow navigation and cannot tab through links. Modern HTML provides the Popover API (popover, popovertarget) which gives native top-layer flyout and light-dismiss without ruining link semantics.

Semantic Target: <button popovertarget="..."> + Popover API
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Native Top Layer, light-dismiss & Esc key support
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~50-70 lines of JS + CSS)

Frequently misimplemented on web navigation links where Tab navigation is broken.

Wiring & Implementation Requirements:

  • <button aria-haspopup="menu" aria-expanded="false"> + <ul role="menu"> + <li role="menuitem">
  • Arrow Up/Down navigation within menu
  • Esc to close and return focus
  • Tab immediately closes menu and moves to next page element

Keyboard Functionality:

  • Enter / Space: Opens menu and focuses first item
  • Arrow Down / Up: Navigates menuitems
  • Escape: Closes menu and focuses button
  • Tab: Closes menu immediately

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "menu button, has popup menu, expanded / collapsed".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~5 lines of HTML)

Browser Top Layer with light-dismiss built in.

Wiring & Implementation Requirements:

  • <button popovertarget="my-popover"> + <div id="my-popover" popover>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Enter / Space: Opens popover
  • Escape: Natively closes popover (light dismiss)
  • Tab: Traverses all interactive elements inside popover normally

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces button trigger and top-layer popover panel.

Real-World Limitations of Native Semantic HTML (Menu Button / Popover):

  • Popover API is supported in modern browsers (Chrome 114+, Firefox 125+, Safari 17+); older legacy browsers require polyfill.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<button popovertarget="..."> + Popover API)
/* Styling Native Popover API */
[popover] {
  border: 1px solid var(--border-default);
  border-radius: 8px;
  padding: 12px;
  background: var(--surface-card);
  box-shadow: 0 10px 25px rgba(0,0,0,0.3);
}
[popover]:popover-open {
  opacity: 1;
}
State Attribute CSS for ARIA
[role="menu"] { position: absolute; background: #1c1b1f; }
💡 Pro Styling Tips:
  • Use the Popover API for flyouts and dropdowns that contain navigation links, and reserve ARIA role="menu" only for desktop-like application action palettes.
Application Widgets ARIA Required (No Native HTML Element)

Tabs

A set of layered panels where only one panel is displayed at a time. Because HTML currently lacks a native <tabs> element, the APG Tabs pattern remains the required accessible pattern.

First Rule Analysis:

Unlike dialogs, accordions, and sliders, HTML does not have a native <tabs> or <tabpanel> element (although WHATWG and OpenUI have active proposals). Therefore, implementing tabbed interfaces requires following the W3C APG Tabs pattern: role="tablist", role="tab", role="tabpanel", aria-selected="true/false", and roving tabindex with ArrowLeft/ArrowRight navigation. Some developers attempt hacks using radio buttons or details, but only the APG ARIA pattern communicates true tabbed semantics to screen readers.

Semantic Target: No native <tabs> element exists in HTML
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS

Run axe-core and Lighthouse against static DOM nodes.

Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
HTML Specification Notice:

No native <tabs> element exists in HTML yet. The W3C APG ARIA Tabs pattern shown on the left is the required standard for accessible tabbed interfaces.

Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~50-70 lines of JS + HTML)

Normative standard required because HTML does not have a native <tabs> element.

Wiring & Implementation Requirements:

  • <div role="tablist" aria-label="..."> container
  • <button role="tab" aria-selected="true/false" aria-controls="panel-id" id="tab-id">
  • <div role="tabpanel" id="panel-id" aria-labelledby="tab-id" tabindex="0">
  • Roving tabindex algorithm (active tab has tabindex="0", inactive have tabindex="-1")
  • ArrowLeft / ArrowRight keyboard listeners to switch tabs
  • Tab key jumps from active tab directly into tabpanel content

Keyboard Functionality:

  • Arrow Left / Right: Navigates between tabs (roving focus)
  • Tab: Jumps directly into active tabpanel content (single tab stop for tablist)
  • Home / End: Focuses first / last tab

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "tab, selected [or unselected], tab 1 of 3". Tabpanel announces associated tab label.

🟢 Semantic HTML Equivalent N/A (ARIA Required) (N/A)

Use the W3C APG ARIA Tabs pattern.

Wiring & Implementation Requirements:

  • NO native <tabs> element exists in HTML specification yet!
  • Can be approximated using <details name="tab-group"> or CSS-only radio buttons, but neither communicates true tab semantics to assistive technologies.

Keyboard Functionality:

  • Without ARIA, each tab button is a separate tab stop (violating expected tablist keyboard efficiency).

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announced as individual buttons or details, lacking tab / tabpanel relationship.

Real-World Limitations of Native Semantic HTML (Tabs):

  • HTML has no native tab widget. WHATWG and OpenUI are developing proposals, but none are standardized.
  • Radio-button tab hacks pollute form data and fail to represent tabpanel relationships to screen readers.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (No native <tabs> element exists in HTML)
/* What developers do when avoiding JS (CSS Radio Tab Hack) */
input[type="radio"].tab-radio {
  position: absolute;
  opacity: 0;
}
.tab-radio:checked + label {
  border-bottom: 2px solid #059669;
  color: #059669;
}
State Attribute CSS for ARIA
[role="tab"][aria-selected="true"] {
  border-bottom: 2px solid #a855f7;
  color: #a855f7;
}
[role="tabpanel"][hidden] {
  display: none;
}
💡 Pro Styling Tips:
  • Always keep tabpanel focusable (tabindex="0") if it contains no focusable interactive children, so keyboard-only users can scroll long content.
Structure & Layout Native Table Preferred; ARIA Grid for Apps

Table vs Data Grid

A tabular presentation of data. Native HTML <table> provides built-in screen reader navigation commands; ARIA role="grid" is reserved for interactive spreadsheet applications.

First Rule Analysis:

Native HTML <table> with <th> scope="col/row" and <caption> gives screen reader users built-in matrix reading shortcuts (e.g. Ctrl+Alt+Arrows in JAWS/NVDA, VO+Arrows in VoiceOver). Replacing tables with <div role="table"> is unnecessary work. Furthermore, developers often misuse role="grid" when they simply have a data table: role="grid" tells assistive technologies to disable standard table navigation in favor of arrow-key cell traversal, which should only be used for interactive widgets like spreadsheets or calendars.

Semantic Target: <table>, <thead>, <tbody>, <tr>, <th>, <td>
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
WCAG 3 Tier
Requirement
Bronze
Core Conformance
Silver
Exceeds Minimum
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
WCAG 3 Tiers
WCAG 3 Tier Requirement
Bronze Core Conformance
Silver Exceeds Minimum
Native screen reader table navigation shortcuts (Ctrl+Alt+Arrows)
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~40 lines of HTML + CSS)

Complete reinvention of standard HTML table elements with zero usability benefit for static data.

Wiring & Implementation Requirements:

  • <div role="table">, <div role="rowgroup">, <div role="row">, <div role="columnheader">, <div role="cell">
  • For role="grid", 2D arrow key cell traversal must be programmed manually with roving tabindex

Keyboard Functionality:

  • Arrow keys navigate cells in role="grid"

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Screen readers must emulate table commands on custom divs.

🟢 Semantic HTML Equivalent Minimal (0 JS) (~10 lines of HTML)

Native browser HTML table.

Wiring & Implementation Requirements:

  • <table>, <caption>, <thead>, <tbody>, <tr>, <th scope="col/row">, <td>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Screen reader users navigate rows and columns with native shortcuts (Ctrl+Alt+Arrows)

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces table dimensions (e.g. "table with 4 columns and 10 rows") and reads column headers automatically.

Real-World Limitations of Native Semantic HTML (Table vs Data Grid):

  • Responsive tables on narrow mobile screens require horizontal overflow wrappers (overflow-x: auto) to avoid breaking layout.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<table>, <thead>, <tbody>, <tr>, <th>, <td>)
table {
  width: 100%;
  border-collapse: collapse;
}
th, td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-subtle);
  text-align: left;
}
th {
  background: var(--surface-elevated);
}
State Attribute CSS for ARIA
.apg-aria-table { display: flex; flex-direction: column; }
💡 Pro Styling Tips:
  • Always use <th scope="col"> and <th scope="row"> to ensure header cell associations are unambiguous.
Inputs & Controls Native Element Preferred

Spinbutton

A stepper input for selecting a numeric value from a defined range. Native <input type="number"> provides native stepper controls, mobile numeric keyboards, and keyboard navigation.

First Rule Analysis:

The APG ARIA spinbutton requires a <div> with role="spinbutton", aria-valuenow, aria-valuemin, aria-valuemax, plus increment and decrement buttons and custom keydown listeners for ArrowUp, ArrowDown, PageUp, PageDown, Home, and End. Native <input type="number"> does all of this natively and automatically triggers numeric keypads on mobile smartphones.

Semantic Target: <input type="number">
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
3
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Native stepper controls & mobile numeric keypad
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~35 lines of JS + HTML)

Manual implementation of number stepping and constraint checking.

Wiring & Implementation Requirements:

  • <div role="spinbutton" tabindex="0" aria-valuenow="1" aria-valuemin="1" aria-valuemax="10">
  • Increment & decrement trigger buttons
  • Keydown listeners for ArrowUp and ArrowDown
  • Manual state sync and display text updating

Keyboard Functionality:

  • Arrow Up / Down: Increments / decrements number value

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "spinbutton, Quantity, 3".

🟢 Semantic HTML Equivalent Minimal (0 JS) (1 line of HTML)

Native browser number input.

Wiring & Implementation Requirements:

  • <input type="number" min="1" max="10" step="1" value="3">
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Arrow Up / Down: Natively increments / decrements number by step

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively announces spinbutton with min, max, and current value.

Real-World Limitations of Native Semantic HTML (Spinbutton):

  • Different browsers render different native stepper spinner arrows; hiding them requires vendor CSS rules.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<input type="number">)
/* Removing native spin buttons if custom UI is required */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
State Attribute CSS for ARIA
.spinbutton-wrapper button { padding: 4px 8px; }
💡 Pro Styling Tips:
  • Native <input type="number"> triggers numeric keypads on iOS and Android automatically.
Structure & Layout Native Element Preferred

Landmarks

Structural landmarks define major regions of a webpage, allowing screen reader users to jump directly between sections. HTML5 landmark elements map natively to ARIA landmark roles.

First Rule Analysis:

Never use <div role="banner"> or <div role="main"> when you can use <header> and <main>. Modern HTML provides explicit elements for every major ARIA landmark: <header> (banner), <nav> (navigation), <main> (main), <aside> (complementary), <footer> (contentinfo), and the modern <search> element (search).

Semantic Target: <header>, <nav>, <main>, <aside>, <footer>, <search>
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
role="banner"
role="navigation"
role="main"
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
<header>
<main>
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (Multiple explicit role attributes)

Redundant when HTML5 landmark tags are available.

Wiring & Implementation Requirements:

  • <div role="banner">, <div role="navigation">, <div role="main">, <div role="contentinfo">
  • Manual role assignment on generic div containers

Keyboard Functionality:

  • Screen reader shortcut keys (D or R) jump between landmarks

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "banner", "main", "navigation".

🟢 Semantic HTML Equivalent Minimal (0 JS) (Native HTML tags)

Zero effort landmark architecture.

Wiring & Implementation Requirements:

  • <header>, <nav>, <main>, <aside>, <footer>, <search>
  • 0 ARIA roles needed

Keyboard Functionality:

  • Screen reader shortcut keys (D or R) jump between HTML5 sections natively

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Natively maps to accessibility landmark roles in all screen readers.

Real-World Limitations of Native Semantic HTML (Landmarks):

  • <header> and <footer> only map to banner and contentinfo when they are direct children of <body> (not scoped within <article> or <section>).
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<header>, <nav>, <main>, <aside>, <footer>, <search>)
main {
  max-width: 1200px;
  margin: 0 auto;
}
header, footer {
  padding: 24px;
}
State Attribute CSS for ARIA
[role="main"] { max-width: 1200px; }
💡 Pro Styling Tips:
  • Use aria-label on <nav> elements (e.g. <nav aria-label="Main Navigation">) to distinguish multiple navigation landmarks on the same page.
Navigation Hybrid Enhancement

Breadcrumb

A navigation trail showing the user’s location within a hierarchical site structure. The standard pattern combines semantic HTML <nav> and <ol> with aria-current="page".

First Rule Analysis:

The breadcrumb pattern represents the ideal synergy between semantic HTML and ARIA. Semantic HTML provides the container (<nav>), the ordered sequence of steps (<ol> and <li>), and the hyperlinks (<a>). ARIA provides the critical attribute aria-current="page" on the active link or element, informing assistive tech users that they are currently on that step.

Semantic Target: <nav aria-label="Breadcrumb"> + <ol> + aria-current="page"
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Using <span> for current page prevents dead links
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~10 lines of HTML)

Clean hybrid pattern requiring only aria-current="page".

Wiring & Implementation Requirements:

  • <nav aria-label="Breadcrumb">
  • <ol> ordered list containing <li> items
  • aria-current="page" on the final link or span

Keyboard Functionality:

  • Tab: Moves sequentially through breadcrumb items

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Breadcrumbs navigation, list 3 items", and on current item announces "current page".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~8 lines of HTML)

Pure HTML list with one ARIA attribute.

Wiring & Implementation Requirements:

  • <nav aria-label="Breadcrumb"><ol><li><a href="...">...</a></li><li><span aria-current="page">...</span></li></ol></nav>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Tab: Moves through links in sequence

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces ordered navigation trail and current page step.

Real-World Limitations of Native Semantic HTML (Breadcrumb):

  • HTML has no native breadcrumb element or current-page attribute; aria-current="page" is universally required.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<nav aria-label="Breadcrumb"> + <ol> + aria-current="page")
nav[aria-label="Breadcrumb"] ol {
  display: flex;
  gap: 8px;
  list-style: none;
}
nav[aria-label="Breadcrumb"] li + li::before {
  content: "/";
  color: var(--text-muted);
  margin-right: 8px;
}
State Attribute CSS for ARIA
[aria-current="page"] { font-weight: bold; }
💡 Pro Styling Tips:
  • Use a <span> with aria-current="page" for the last item rather than an <a> tag to avoid confusing unclickable self-links.
Application Widgets ARIA Required for App Trees; Nested Details for Docs

Tree View

A hierarchical list with parent and child items that can be expanded and collapsed, typical in IDE file trees and file managers.

First Rule Analysis:

For true application file explorer widgets, the APG Tree View pattern (role="tree", role="treeitem", aria-expanded) is required to deliver the expected single-tab-stop roving focus and hierarchical arrow navigation (ArrowRight expands/enters child, ArrowLeft collapses/jumps to parent). For simple hierarchical reading documents or site maps, nested <details> and <summary> elements provide an accessible zero-JS alternative.

Semantic Target: Nested <details> or ARIA role="tree"
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
  • 📂 src/
    • 📄 index.astro
    • 📄 layout.astro
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
📂 src/

📄 index.astro

📄 layout.astro

Nested details works without JS, but lacks single-tab roving focus
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Extreme Effort (~100 lines of recursive JS)

Hierarchical roving tabindex and recursive expand/collapse tracking.

Wiring & Implementation Requirements:

  • <ul role="tree">, <li role="treeitem" aria-expanded="false">, <ul role="group">
  • Roving tabindex across entire tree hierarchy
  • ArrowRight: expands or descends into children
  • ArrowLeft: collapses or ascends to parent
  • ArrowDown / ArrowUp: moves sequentially through visible items

Keyboard Functionality:

  • Arrow keys navigate tree levels with roving tabindex
  • Enter / Space activates item

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "treeitem, level 1, expanded 1 of 4".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~10 lines of HTML)

Zero JS nested document tree.

Wiring & Implementation Requirements:

  • Nested <details> and <summary> tags for document trees
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Enter / Space: toggles open/closed
  • Tab: moves to next focusable element

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces disclosure levels natively.

Real-World Limitations of Native Semantic HTML (Tree View):

  • Nested <details> lacks the single-tab-stop roving focus expected in desktop application file managers.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (Nested <details> or ARIA role="tree")
.nested-details-tree details {
  padding-left: 14px;
}
State Attribute CSS for ARIA
[role="treeitem"]:focus { outline: 2px solid #a855f7; }
💡 Pro Styling Tips:
  • For reading content and sitemaps, nested details is vastly simpler and requires zero maintenance.
Dialogs & Overlays Hybrid Enhancement

Alert

A time-sensitive message that communicates important information to the user without receiving focus. HTML <output> natively maps to a polite live region, while role="alert" provides assertive interruption.

First Rule Analysis:

For general form feedback and calculated results, the native HTML <output> element provides an automatic live region with role="status" and aria-live="polite". When an urgent error or critical notification requires immediate screen reader interruption, the ARIA role="alert" (equivalent to aria-live="assertive") is specifically required.

Semantic Target: <output> or role="alert"
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Status: Idle <output> maps natively to role="status" & aria-live="polite"
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Medium Effort (~5 lines of JS + HTML)

Requires dynamic DOM node injection into existing live container.

Wiring & Implementation Requirements:

  • <div role="alert"> (or aria-live="assertive" + aria-atomic="true")
  • Container must exist in DOM before content is dynamically injected

Keyboard Functionality:

  • Not in Tab sequence; does not receive focus

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Immediately interrupts speech to announce alert content.

🟢 Semantic HTML Equivalent Minimal (0 JS) (1 line of HTML)

Native HTML output tag.

Wiring & Implementation Requirements:

  • <output for="inputs">Feedback text</output>
  • Natively has role="status" and aria-live="polite"

Keyboard Functionality:

  • Not focusable; passive status container

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Politely announced when output value changes.

Real-World Limitations of Native Semantic HTML (Alert):

  • <output> announces politely; it cannot assertively interrupt a screen reader during urgent critical errors (where role="alert" is needed).
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<output> or role="alert")
output {
  display: block;
  padding: 10px 14px;
  background: var(--surface-card);
  border-radius: 6px;
}
State Attribute CSS for ARIA
[role="alert"] { background: rgba(220, 38, 38, 0.2); border: 1px solid #dc2626; }
💡 Pro Styling Tips:
  • Never place role="alert" on elements with keyboard focus; alerts are designed for passive non-focused announcement.
Dialogs & Overlays Hybrid: ARIA Tooltip + Anchor Positioning

Tooltip

A contextual popup that displays information describing an element when focused or hovered. Modern CSS Anchor Positioning and Popover API dramatically simplify accessible tooltips.

First Rule Analysis:

The native HTML title attribute has significant accessibility defects: it does not work on touchscreens, cannot be resized, does not support custom contrast or keyboard delays, and violates WCAG 1.4.13 (Content on Hover or Focus). The APG pattern using aria-describedby and role="tooltip" remains essential, but modern CSS Anchor Positioning (anchor()) and the Popover API (popover="hint") now make the visual anchoring robust and pure CSS.

Semantic Target: aria-describedby + Popover API / title
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Note: title has mobile and contrast limitations
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~40 lines of JS + CSS positioning)

Requires coordinate math to avoid edge clipping and timer management.

Wiring & Implementation Requirements:

  • <button aria-describedby="tip-id">
  • <div role="tooltip" id="tip-id" hidden>
  • Event listeners for mouseenter, mouseleave, focus, blur, and Escape key dismissal

Keyboard Functionality:

  • Focus reveals tooltip
  • Escape dismisses tooltip without losing focus (WCAG 1.4.13)

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Reads tooltip text as accessible description after the button label.

🟢 Semantic HTML Equivalent Minimal (0 JS for title) (1 attribute)

Native title attribute.

Wiring & Implementation Requirements:

  • <button title="Tooltip text"> or popover="hint"
  • 0 lines of JavaScript needed with title

Keyboard Functionality:

  • Hover or focus shows native tooltip in some browsers (unreliable in title)

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Reads title attribute if no other description exists.

Real-World Limitations of Native Semantic HTML (Tooltip):

  • The HTML title attribute CANNOT be styled with CSS, does not work on mobile touchscreens, cannot be zoomed without page zoom, and cannot be dismissed with Escape in many browsers (violating WCAG 1.4.13).
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (aria-describedby + Popover API / title)
/* Modern Anchor Positioning for Tooltips */
.anchor-btn {
  anchor-name: --tip-btn;
}
.modern-tip {
  position: absolute;
  position-anchor: --tip-btn;
  top: anchor(bottom);
  left: anchor(center);
  transform: translateX(-50%);
}
State Attribute CSS for ARIA
[role="tooltip"] { position: absolute; background: #000; color: #fff; padding: 4px 8px; border-radius: 4px; }
💡 Pro Styling Tips:
  • Never put essential information only in a tooltip; always ensure primary instructions are visible on screen.
Application Widgets ARIA Required for Application Toolbars

Toolbar

A collection of commonly used controls arranged in a single tab stop where users navigate with arrow keys.

First Rule Analysis:

In complex applications (e.g. rich text editors), having 20 formatting buttons create 20 separate Tab stops severely degrades keyboard navigation efficiency. The APG Toolbar pattern groups related controls into a single tab stop: Tab enters the toolbar, Arrow keys navigate between controls, and Tab exits to the next document element.

Semantic Target: <fieldset> or <div role="toolbar">
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Single Tab stop; use ← → arrow keys
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Editor Tools
Standard Tab sequence across individual buttons
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~40 lines of JS + HTML)

Required for complex applications to prevent Tab key fatigue.

Wiring & Implementation Requirements:

  • <div role="toolbar" aria-label="Formatting">
  • Roving tabindex across buttons (first button has tabindex="0", others have tabindex="-1")
  • ArrowLeft / ArrowRight listeners to cycle focus
  • Home / End to jump to first / last button

Keyboard Functionality:

  • Arrow keys navigate toolbar buttons; Tab exits entire toolbar

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "toolbar, Formatting".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~5 lines of HTML)

Standard HTML button group.

Wiring & Implementation Requirements:

  • <fieldset><legend class="sr-only">Formatting</legend><button>...</button></fieldset>
  • 0 lines of JavaScript needed

Keyboard Functionality:

  • Each button is an individual Tab stop in standard HTML

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces fieldset legend and individual buttons.

Real-World Limitations of Native Semantic HTML (Toolbar):

  • HTML button groups have no built-in roving tabindex; every button requires a Tab press, creating keyboard navigation clutter in tool-dense apps.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<fieldset> or <div role="toolbar">)
.toolbar-group {
  display: inline-flex;
  gap: 4px;
  background: var(--surface-card);
  padding: 4px;
  border-radius: 6px;
}
State Attribute CSS for ARIA
[role="toolbar"] button:focus { outline: 2px solid #a855f7; }
💡 Pro Styling Tips:
  • Use role="toolbar" in rich applications (like text editors or drawing canvases) to keep the tab order clean.
Application Widgets ARIA Required for 2D Spreadsheet & Data Grid Navigation

Grid (Data Grid & Editable Tables)

A composite interactive widget containing tabular rows and cells navigable in two dimensions using arrow keys. Unlike static HTML tables, a grid treats cells as active focus targets.

First Rule Analysis:

Under the First Rule of ARIA, HTML <table> is specifically intended for presenting static structured tabular data, where screen readers operate in virtual reading mode. When building an editable spreadsheet or interactive data grid where users need 2D directional arrow-key navigation (Up/Down/Left/Right), cell editing (Enter/F2), and selection models without tabbing through every cell, HTML provides no native equivalent. The APG role="grid", role="row", and role="gridcell" with roving tabindex or aria-activedescendant are required.

Semantic Target: <table> with interactive cell controls
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
ID Criterion Severity Status
ISS-101 1.4.3 Contrast High Open
ISS-102 2.1.1 Keyboard Critical In Review
ISS-103 4.1.2 Name/Role Medium Resolved
Use ↑ ↓ ← → arrow keys to navigate 2D cells; click/edit Status
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
WCAG Issue Tracker (Native HTML Table)
ID Criterion Severity Status
ISS-101 1.4.3 Contrast High
ISS-102 2.1.1 Keyboard Critical
Standard Tab jumps between inputs; screen readers use native table keys
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Extreme Effort (~150-250 lines of JS + ARIA logic)

2D coordinates tracking, roving tabindex matrix, edit mode state management, and assistive tech coordinate synchronization.

Wiring & Implementation Requirements:

  • Container element has role="grid" and aria-label or aria-labelledby.
  • Row elements have role="row".
  • Header cells have role="columnheader" or role="rowheader".
  • Data cells have role="gridcell".
  • Roving tabindex (tabindex="0" on active cell, tabindex="-1" on all others) or aria-activedescendant on the grid.
  • Arrow key handlers for 2D cell-by-cell directional navigation.
  • Enter/F2 toggles edit mode inside editable cells; Escape exits edit mode.
  • Single Tab stop: Tab moves focus into and out of the composite grid widget.

Keyboard Functionality:

  • Single Tab stop for entire grid container
  • Arrow keys (← ↑ → ↓) navigate cells in 2D space
  • Home / End moves to first / last cell in current row
  • Enter or F2 activates cell editing mode; Escape cancels

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Grid, N rows by M columns, row X, column Y: [content]". Changes to edit mode announced dynamically.

🟢 Semantic HTML Equivalent Minimal (0 JS) (~20 lines of HTML)

Standard native semantic table with embedded form controls.

Wiring & Implementation Requirements:

  • Standard <table> element with <thead>, <tbody>, <tr>, <th>, <td>.
  • Native <input> or <button> inside cells for interactivity.
  • Scope attributes (scope="col", scope="row") on headers.

Keyboard Functionality:

  • Tab moves sequentially across every single interactive element in the table
  • Arrow keys navigate inside individual form inputs rather than across table cells

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Screen reader virtual table navigation (Ctrl+Alt+Arrows in NVDA/JAWS; VO+Arrows in VoiceOver).

Real-World Limitations of Native Semantic HTML (Grid (Data Grid & Editable Tables)):

  • Native tables have no single-tab roving keyboard navigation; every input in every cell is an individual Tab stop, making 50-row tables exhausting to tab through.
  • No built-in 2D arrow-key cell navigation without custom JavaScript.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<table> with interactive cell controls)
.data-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}
.data-table-wrap table {
  width: 100%;
  border-collapse: collapse;
}
.data-table-wrap th, .data-table-wrap td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-subtle);
}
State Attribute CSS for ARIA
[role="grid"] [role="gridcell"]:focus-visible {
  outline: 2px solid var(--accent-blue);
  outline-offset: -2px;
  background: rgba(182, 196, 255, 0.15);
}
💡 Pro Styling Tips:
  • Only use role="grid" when cells are truly interactive or editable (like Airtable or Excel). For read-only data, native <table> is always superior.
Inputs & Controls Native Element Preferred

Listbox

A widget that presents a visible, scrollable list of options where users can select one or more items. Native HTML <select size="N"> provides this behavior with zero JavaScript.

First Rule Analysis:

Under the First Rule of ARIA, HTML provides a native, perfectly accessible listbox using <select size="N"> for single-selection and <select multiple size="N"> for multi-selection. The native element automatically handles keyboard navigation (Arrow keys, Home, End, Shift+Arrows for multi-select, type-ahead character search) and form submission. The APG ARIA pattern requires custom role="listbox", role="option", aria-selected, roving tabindex or aria-activedescendant, and extensive JavaScript.

Semantic Target: <select size="N"> or <select multiple>
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
  • WCAG 2.1 Level AA
  • WCAG 2.2 Level AA (Current Standard)
  • WCAG 2.2 Level AAA
  • WCAG 3.0 Bronze Draft
Navigate with ↑ ↓ arrow keys; Space to select
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Native <select size="4"> provides zero-JS listbox with typeahead
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~50-80 lines of JS + ARIA)

Selection state management, roving tabindex or aria-activedescendant sync, scrollIntoView positioning, and type-ahead logic.

Wiring & Implementation Requirements:

  • Container element has role="listbox", tabindex="0", and aria-label or aria-labelledby.
  • Child item elements have role="option".
  • Selected option has aria-selected="true" (unselected have aria-selected="false").
  • For multi-selection, container has aria-multiselectable="true".
  • Roving tabindex or aria-activedescendant management in JavaScript.

Keyboard Functionality:

  • Single Tab stop on listbox container
  • Arrow keys (↑ / ↓) navigate and select options
  • Home / End moves to boundaries
  • Space toggles selection in multi-select mode

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Listbox, N items, [Option Name], X of N, selected".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~5 lines of HTML)

Native declarative HTML with built-in form serialization.

Wiring & Implementation Requirements:

  • <select size="4"> for single-select scrollable listbox.
  • <select multiple size="4"> for multi-select listbox.
  • <option value="...">Option Label</option> tags.
  • Associated <label for="...">.

Keyboard Functionality:

  • Arrow keys navigate options natively
  • Shift+Arrow keys select contiguous ranges in multi-select
  • Ctrl+Click / Cmd+Click selects non-contiguous items

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Native OS/browser listbox announcements with item count, position, and selected state.

Real-World Limitations of Native Semantic HTML (Listbox):

  • Custom styling of native <option> elements (such as embedded avatars or custom badge markup) is historically restricted, though modern browser Customizable Select standards are closing this gap.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<select size="N"> or <select multiple>)
.semantic-listbox {
  width: 100%;
  padding: 6px;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: inherit;
}
.semantic-listbox option {
  padding: 8px 12px;
  border-radius: 4px;
}
State Attribute CSS for ARIA
[role="listbox"] {
  border: 1px solid var(--border-default);
  background: var(--surface-card);
  border-radius: var(--radius-sm);
}
[role="option"][aria-selected="true"] {
  background: rgba(182, 196, 255, 0.2);
  color: var(--text-primary);
}
💡 Pro Styling Tips:
  • Always set size="4" or greater on <select> to render as a listbox rather than a dropdown.
Navigation Semantic HTML Preferred for Web Navigation

Menu and Menubar

A desktop-application-style horizontal menu bar with dropdown submenus. For website navigation, semantic <nav> with standard links is strongly preferred over ARIA menubar.

First Rule Analysis:

The W3C APG explicitly cautions that the ARIA menubar pattern is intended for web applications mimicking desktop software menus (e.g. Google Docs File/Edit/View), NOT for website site navigation bars. Using role="menubar" on site navigation breaks standard tab navigation and hides links from screen reader landmark lists. For site navigation, the First Rule dictates using native <nav> with semantic lists (<ul>/<li>) and standard links (<a>) or Popover API buttons.

Semantic Target: <nav> + <ul> + <li> + <a> / Popover API
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Use ← → between menus; ↓ opens dropdown; Esc closes
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
W3C APG advice: Websites should use <nav> + links, not ARIA menubar
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Extreme Effort (~100-160 lines of JS + ARIA logic)

Bi-directional arrow navigation, submenu positioning, hover/focus intent timers, and Escape key focus restoration.

Wiring & Implementation Requirements:

  • Top-level container has role="menubar" with aria-label.
  • Menu item buttons have role="menuitem" (or menuitemcheckbox / menuitemradio).
  • Items with submenus have aria-haspopup="true" and aria-expanded="false/true".
  • Submenus have role="menu" and aria-labelledby.
  • Arrow-key navigation in two dimensions (horizontal across menubar, vertical inside menus).
  • Escape dismisses submenus and restores focus to menubar parent.

Keyboard Functionality:

  • Single Tab stop for entire menubar
  • Left / Right arrows navigate horizontal menubar items
  • Down arrow opens submenus and navigates down
  • Escape closes submenu and returns focus to top level

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Menubar, N items" and "Menuitem, has submenu, expanded/collapsed".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~15 lines of HTML + CSS)

Semantic HTML markup; zero JavaScript required with Popover API.

Wiring & Implementation Requirements:

  • <nav aria-label="Site Navigation"> sectioning element.
  • Unordered list (<ul>) and list items (<li>) for page structure.
  • Native links (<a href="...">) for pages.
  • Optional <button popovertarget="..."> for accessible disclosure submenus.

Keyboard Functionality:

  • Tab navigates sequentially through every navigation link
  • Enter activates link or opens popover dropdown

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Navigation landmark, list with N items, link, [Link Text]".

Real-World Limitations of Native Semantic HTML (Menu and Menubar):

  • Hover-only CSS dropdown menus frequently collapse when users navigate with screen magnifiers or switch to keyboard; pairing with Popover API ensures click/Enter persistence.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<nav> + <ul> + <li> + <a> / Popover API)
.semantic-nav-list {
  display: flex;
  gap: 16px;
  list-style: none;
}
.semantic-nav-list a {
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 600;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
}
.semantic-nav-list a:hover {
  background: var(--surface-card-hover);
  color: var(--accent-blue);
}
State Attribute CSS for ARIA
[role="menubar"] {
  display: flex;
  background: var(--surface-elevated);
  border-radius: var(--radius-sm);
  padding: 4px;
}
[role="menuitem"]:focus {
  background: var(--accent-blue);
  color: var(--on-accent);
}
💡 Pro Styling Tips:
  • Never use role="menubar" for website page navigation. Reserve it strictly for application menu bars (like Google Docs or VS Code).
Dialogs & Overlays Native Element Preferred

Alert Dialog (Modal Prompt)

A modal dialog that interrupts the user workflow to communicate an urgent message and require immediate confirmation or cancellation (e.g. confirming permanent deletion).

First Rule Analysis:

Native HTML <dialog> invoked via .showModal() natively traps keyboard focus, renders in the top-layer, dims background content with ::backdrop, handles Escape key dismissal, and restores focus upon closing. For an alert dialog, placing the autofocus attribute on the least destructive button (e.g. Cancel) ensures screen readers immediately announce the message while preventing accidental confirmation.

Semantic Target: <dialog> with autofocus on Cancel
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Focus placed on least destructive "Cancel" button; Esc closes
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features

Discard Unsaved Changes? (Native)

You have 3 unsaved WCAG rule overrides. Leaving will discard them.

Native <dialog> traps focus, Esc cancels, autofocus targets safe button
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~45 lines of JS + ARIA logic)

Focus trapping, restoring previous active element, Escape listeners, and background inerting.

Wiring & Implementation Requirements:

  • Overlay window has role="alertdialog" and aria-modal="true".
  • aria-labelledby points to dialog title.
  • aria-describedby points to the alert message body.
  • Initial focus placed on the least destructive action button (Cancel).
  • JavaScript focus trap preventing Tab from escaping into main page.
  • Background marked inert or hidden via aria-hidden="true".

Keyboard Functionality:

  • Focus trapped strictly inside alertdialog buttons
  • Escape cancels and closes
  • Tab cycles between Cancel and Confirm

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Screen reader automatically reads alert title and description, announcing "Alert dialog, [Title], [Message], Cancel button, focused".

🟢 Semantic HTML Equivalent Minimal (1-2 lines JS) (1 line JS (dialog.showModal()))

100% native browser focus trap and top-layer rendering.

Wiring & Implementation Requirements:

  • <dialog class="alert-dialog"> element.
  • autofocus attribute on Cancel button.
  • Invoked with dialog.showModal().

Keyboard Functionality:

  • Native top-layer focus trapping
  • Escape closes natively with cancel event
  • Initial focus set via autofocus

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Native top-layer dialog announcement with immediate speech of content.

Real-World Limitations of Native Semantic HTML (Alert Dialog (Modal Prompt)):

  • Requires dialog::backdrop CSS styling for custom tint and blur effects.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<dialog> with autofocus on Cancel)
.semantic-alert-dialog {
  border: 2px solid var(--accent-rose);
  border-radius: var(--radius-lg);
  padding: 24px;
  background: var(--surface-card);
  color: var(--text-primary);
  max-width: 440px;
}
.semantic-alert-dialog::backdrop {
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(4px);
}
State Attribute CSS for ARIA
[role="alertdialog"] {
  border: 2px solid #ef4444;
  background: var(--surface-card);
  border-radius: var(--radius-lg);
  padding: 24px;
}
💡 Pro Styling Tips:
  • Always place autofocus on the CANCEL button for destructive alert dialogs so pressing Enter accidentally cannot trigger data loss.
Structure & Layout Semantic HTML with Targeted ARIA

Feed (Dynamic Content Stream)

A scrollable list of articles that automatically loads new content as the user scrolls, supporting PageUp/PageDown article-to-article keyboard navigation.

First Rule Analysis:

Under the First Rule of ARIA, HTML provides the semantic building blocks for dynamic streams using <section> or <main> with child <article> elements. The ARIA role="feed" pattern is an enhancement layered on top of semantic articles that introduces PageUp/PageDown keyboard shortcuts for jumping between article boundaries and aria-busy="true" while fetching new batches.

Semantic Target: <section aria-label="..."> + <article> stream
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS

WCAG 2.2 Reaches REC Status

Focus appearance, dragging movements, and accessible authentication are now formal recommendations.

WCAG 3 Working Draft Updated

Explorations into scoring models, task-based outcomes, and equity metrics continue.

Use Page Up / Page Down to jump between articles
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features

WCAG 2.2 Recommendation

Standardized accessible authentication, focus appearance, and dragging.

WCAG 3 Working Draft

Evaluating holistic accessibility outcomes and disability equity.

Clean semantic HTML without complex feed roving focus JS
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~60-90 lines of JS + ARIA logic)

PageUp/PageDown focus management, scroll triggers, aria-busy states, and setsize calculation.

Wiring & Implementation Requirements:

  • Container has role="feed" and aria-label or aria-labelledby.
  • Each post item has role="article" and tabindex="0" (or contains focusable heading).
  • Articles specify aria-posinset and aria-setsize when total count is known.
  • While new articles are being fetched asynchronously, container has aria-busy="true".
  • PageUp / PageDown keyboard event listeners to jump focus between articles.

Keyboard Functionality:

  • PageUp / PageDown moves focus between article boundaries
  • Tab explores interactive buttons and links within current article
  • Ctrl+End jumps past the infinite feed

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Feed, Article X of Y, [Headline]". Dynamically announces when new articles are loaded.

🟢 Semantic HTML Equivalent Low (~15 lines of JS (IntersectionObserver))

Standard semantic HTML articles with standard web APIs.

Wiring & Implementation Requirements:

  • <section aria-label="Activity Feed"> or <main>.
  • Semantic <article> elements with header, time, and content.
  • IntersectionObserver for progressive infinite scroll.

Keyboard Functionality:

  • Standard Tab navigation across article interactive controls
  • Standard spacebar or PageDown viewport scrolling

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces section landmark and article landmarks with heading hierarchy.

Real-World Limitations of Native Semantic HTML (Feed (Dynamic Content Stream)):

  • Native HTML does not provide keyboard shortcuts to jump directly from article to article; keyboard users must Tab through all controls in an article to reach the next one unless using heading navigation (H key in screen readers).
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<section aria-label="..."> + <article> stream)
.semantic-feed {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 600px;
}
.semantic-feed article {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 16px;
}
State Attribute CSS for ARIA
[role="feed"] [role="article"]:focus-visible {
  outline: 2px solid var(--accent-blue);
  outline-offset: 2px;
}
💡 Pro Styling Tips:
  • Always provide a keyboard shortcut (like Ctrl+End or an explicit skip link) to allow keyboard users to jump past infinite feeds to footer content.
Inputs & Controls Semantic Dual Inputs or Hybrid ARIA

Slider (Multi-Thumb Range)

A slider featuring two or more draggable thumbs on a single rail (e.g. minimum and maximum price filter). HTML currently lacks a native dual-range input element.

First Rule Analysis:

HTML does not yet provide a native <input type="range" multiple> element. The accessible semantic alternative under the First Rule is pairing two native inputs: either two adjacent <input type="range"> sliders ("Minimum Budget" and "Maximum Budget") or two paired <input type="number"> controls. For a custom single-rail dual-thumb visual presentation, ARIA role="slider" attributes on both handles are required.

Semantic Target: Dual <input type="range"> or paired <input type="number">
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Budget Range: $25 - $75
Tab to select thumb; ← → arrows adjust without crossing
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Budget Range ($)
$25
$75
Paired native <input type="range"> controls; full form and touch support
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~80-120 lines of JS + ARIA logic)

Dual thumb coordinate math, collision boundary checks, touch/mouse drag handlers, and twin ARIA state synchronization.

Wiring & Implementation Requirements:

  • Each thumb has role="slider", tabindex="0", aria-valuenow, aria-valuemin, aria-valuemax.
  • Explicit labels via aria-label (e.g. "Minimum Price" and "Maximum Price").
  • Collision prevention logic: Min thumb cannot exceed Max thumb value.
  • Active track highlight indicating selected range between the two thumbs.

Keyboard Functionality:

  • Tab moves between Min Thumb and Max Thumb
  • Arrow keys adjust focused thumb position
  • Home / End moves to permitted extremes

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Minimum price slider, $X, min $Y, max $Z" and "Maximum price slider, $A".

🟢 Semantic HTML Equivalent Low (~10 lines of HTML + 5 lines JS)

Two standard HTML range inputs with light synchronization logic.

Wiring & Implementation Requirements:

  • Two <input type="range"> elements with explicit <label> tags (Min & Max).
  • Or two <input type="number"> controls with min/max bounds.

Keyboard Functionality:

  • Native arrow key increments and Home/End on individual range sliders
  • Tab moves between the two inputs

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Native range slider announcements with complete browser accessibility.

Real-World Limitations of Native Semantic HTML (Slider (Multi-Thumb Range)):

  • HTML has no single native control that paints two thumbs on one track; rendering a visual dual-thumb slider requires custom CSS or overlaying two transparent sliders.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (Dual <input type="range"> or paired <input type="number">)
.dual-range-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dual-range-group input[type="range"] {
  accent-color: var(--accent-emerald);
}
State Attribute CSS for ARIA
.apg-range-rail {
  position: relative;
  height: 8px;
  background: var(--surface-elevated);
  border-radius: 4px;
}
.apg-range-thumb {
  position: absolute;
  width: 22px;
  height: 22px;
  background: #a855f7;
  border: 2px solid #fff;
  border-radius: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
💡 Pro Styling Tips:
  • Always provide numeric text readouts next to multi-thumb sliders so users know exact current values without having to calculate thumb pixel offsets.
Application Widgets ARIA Required for Hierarchical 2D Grid

Treegrid (Hierarchical Data Grid)

A composite widget combining a tree view and a data grid, presenting hierarchical tabular data with expandable rows and 2D cell keyboard navigation.

First Rule Analysis:

HTML does not support a native hierarchical grid with row expansion and 2D cell arrow-key navigation. While nested <table> inside <details> can display hierarchical data statically, an application treegrid where users navigate cells across parent and child rows requires role="treegrid", role="row", aria-expanded, aria-level, and role="gridcell".

Semantic Target: <table> + nested <details> (Document only)
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Name Size Kind
📂 src/ -- Folder
📄 index.astro 124 KB Astro Template
📄 patterns.ts 152 KB TypeScript
↑ ↓ moves rows; ← collapses/parents; → expands/children
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Name Size Kind
📂 src/ -- Folder
 📄 index.astro 124 KB Astro Template
 📄 patterns.ts 152 KB TypeScript
HTML lacks native treegrid; ARIA treegrid is required for 2D roving keys
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern Extreme Effort (~180-260 lines of JS + ARIA logic)

Hierarchical node tree management, row collapse/reveal animations, 2D matrix navigation, and aria-level sync.

Wiring & Implementation Requirements:

  • Container has role="treegrid" and aria-label.
  • Rows have role="row", aria-level="1/2/3", and aria-setsize.
  • Expandable parent rows have aria-expanded="true/false".
  • Cells have role="gridcell" with roving tabindex.
  • Two-dimensional directional arrow key handling.

Keyboard Functionality:

  • Single Tab stop for entire treegrid container
  • Arrow keys navigate in 2D space across rows and columns
  • Right / Left arrows expand and collapse hierarchical rows

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Treegrid, row X of Y, level Z, expanded/collapsed, column Name: [value]".

🟢 Semantic HTML Equivalent Minimal (0 JS) (~25 lines of HTML)

HTML table with nested details; static document structure.

Wiring & Implementation Requirements:

  • Standard <table> with indented text or nested <details> elements inside cells.

Keyboard Functionality:

  • Tab navigates sequentially through disclosure triggers and links
  • Space toggles <details> open/closed

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces standard table with nested disclosure widgets.

Real-World Limitations of Native Semantic HTML (Treegrid (Hierarchical Data Grid)):

  • Native tables have no semantic concept of row hierarchy or child levels, and cannot support 2D arrow-key grid navigation.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (<table> + nested <details> (Document only))
.treegrid-sem-table {
  width: 100%;
  border-collapse: collapse;
}
.treegrid-sem-table td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-subtle);
}
State Attribute CSS for ARIA
[role="treegrid"] [role="gridcell"]:focus-visible {
  outline: 2px solid var(--accent-blue);
  background: rgba(182, 196, 255, 0.15);
}
💡 Pro Styling Tips:
  • Only implement role="treegrid" for complex enterprise data management (like file explorers with metadata columns or accounting workbooks).
Application Widgets Hybrid CSS / ARIA Splitter

Window Splitter (Resizable Split Pane)

A movable separator between two panes that enables keyboard and mouse resizing of adjacent layout areas.

First Rule Analysis:

For simple layout resizing, modern CSS provides resize: horizontal with overflow: auto natively without any ARIA. For rich interactive application split panes, the ARIA separator pattern (role="separator", tabindex="0", aria-valuenow, aria-valuemin, aria-valuemax) communicates pane dimensions to screen readers and enables arrow key resizing. Alternatively, an accessible <input type="range"> labeled "Pane Divider" can semantically control flex-basis.

Semantic Target: CSS resize property or <input type="range"> controlling flex
⚡ Interactive Sandbox & Live AT Inspector
🟣 W3C APG (ARIA) Role, states & keyboard JS
Auditor View

Contrast: 7.2:1 (Pass AAA)

Component Code
<button role="switch">
Use ← → arrow keys to resize panes; Home/End for extremes
Live AT State: Loading state...
🟢 Semantic HTML Native browser engine features
Resizable Box (CSS resize: horizontal)

Drag bottom-right handle or use arrow keys if focused.

Native CSS resize property requires 0 JavaScript to resize
Live AT State: Loading state...

🛠️ Implementation Blueprint: What's Required to Make It Work

🟣 W3C APG ARIA Pattern High Effort (~70-110 lines of JS + ARIA logic)

Pointer drag listeners, percentage calculations, min/max bounding, aria-valuenow updates, and keyboard handlers.

Wiring & Implementation Requirements:

  • Divider element has role="separator" and tabindex="0".
  • aria-valuenow, aria-valuemin, aria-valuemax defining current and allowed percentage/pixel size.
  • aria-orientation="vertical" (for horizontal divider) or "horizontal" (for vertical divider).
  • aria-controls referencing the ID of the pane being resized.
  • Arrow key handlers for keyboard resizing and pointer event drag listeners.

Keyboard Functionality:

  • Tab moves focus to the window splitter divider
  • Arrow keys (← / →) resize the adjacent panes
  • Home / End collapses or expands to bounds
  • Enter toggles default width

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Announces "Splitter, N percent, min X, max Y".

🟢 Semantic HTML Equivalent Minimal (0 JS for CSS; ~5 lines JS for flex range) (3 lines CSS (resize: horizontal))

Modern CSS resize property on layout containers.

Wiring & Implementation Requirements:

  • CSS resize: horizontal; overflow: auto; on container pane.
  • Or semantic <input type="range" aria-label="Pane divider"> controlling flex-basis in CSS.

Keyboard Functionality:

  • Native range slider arrow keys for keyboard resizing

Screen Reader (AT) Announcement:

🗣️ Screen Reader:

Native range slider announcement.

Real-World Limitations of Native Semantic HTML (Window Splitter (Resizable Split Pane)):

  • CSS resize: horizontal renders a bottom-right corner gripper that is not keyboard operable without pairing with an accessible range input control.
🎨 Inspect CSS Customization Recipes, Code & Specifications
Modern CSS for Semantic HTML (CSS resize property or <input type="range"> controlling flex)
.css-resizable-pane {
  resize: horizontal;
  overflow: auto;
  min-width: 120px;
  max-width: 400px;
  border: 1px solid var(--border-default);
  padding: 12px;
  background: var(--surface-card);
}
State Attribute CSS for ARIA
[role="separator"][aria-orientation="vertical"] {
  width: 8px;
  cursor: col-resize;
  background: var(--border-default);
  transition: background 0.2s;
}
[role="separator"]:focus-visible {
  outline: 2px solid var(--accent-blue);
  background: var(--accent-blue);
}
💡 Pro Styling Tips:
  • Always satisfy WCAG 2.2 SC 2.5.7 (Dragging Movements) by providing arrow keys or step buttons alongside mouse drag gestures on splitters.