Skip to main content

Accessibility Testing Quick Reference

A lookup page for accessibility checks: which WCAG criterion covers what, the numbers to test against, and the commands for tools and screen readers.

How to use this page

This page is for looking things up, not for learning from scratch. New to accessibility? Start with the accessibility cheat sheet, which explains each idea with a broken-vs-fixed example. For the ordered plan, see the accessibility learning path.

Quick Navigation​

Standards: WCAG 2.2 AA by check · Numbers to remember

Testing: Manual check routine · Keyboard expectations · Screen-reader commands · ARIA patterns

Automation: axe tags and rules · Playwright assertions · Other tools

Reporting: Issue template · Severity


WCAG 2.2 AA by check​

AreaCriterion (level)Pass when
Images1.1.1 Non-text Content (A)Meaningful images have alt text; decorative have alt=""
Media1.2.2 Captions (A), 1.2.5 Audio Description (AA)Videos captioned; key visuals described
Structure1.3.1 Info and Relationships (A)Headings, lists, tables, labels are real HTML, not just styling
Order1.3.2 Meaningful Sequence (A)Reading order makes sense
Orientation1.3.4 Orientation (AA)Works portrait and landscape
Input purpose1.3.5 Identify Input Purpose (AA)autocomplete on personal-data fields
Colour1.4.1 Use of Color (A)Colour is never the only signal
Contrast1.4.3 Contrast (Minimum) (AA)Text 4.5:1, large text 3:1
Resize1.4.4 Resize Text (AA)Usable at 200% zoom
Images of text1.4.5 (AA)Real text, not pictures of text
Reflow1.4.10 Reflow (AA)No sideways scroll at 320 px width
Non-text contrast1.4.11 (AA)Controls and focus indicators 3:1
Text spacing1.4.12 (AA)No loss when spacing is increased
Hover/focus content1.4.13 (AA)Dismissible, hoverable, persistent
Keyboard2.1.1 Keyboard (A), 2.1.2 No Keyboard Trap (A)Everything works by keyboard; you can always leave
Time2.2.1 Timing Adjustable (A), 2.2.2 Pause, Stop, Hide (A)Time limits adjustable; motion can be paused
Flashing2.3.1 Three Flashes (A)No more than 3 flashes per second
Bypass2.4.1 Bypass Blocks (A)Skip link or landmarks
Title2.4.2 Page Titled (A)Descriptive <title>
Focus order2.4.3 (A)Logical order
Link purpose2.4.4 (A)Link text (with context) says where it goes
Headings/labels2.4.6 (AA)Descriptive headings and labels
Focus visible2.4.7 (AA)Always visible
Focus not obscured2.4.11 (AA)Not hidden by sticky bars
Pointer2.5.1–2.5.3 (A), 2.5.7 Dragging (AA), 2.5.8 Target Size (AA)Simple alternatives to gestures/dragging; 24 px targets; label in name
Language3.1.1 (A), 3.1.2 (AA)lang on the page and on foreign-language parts
Predictable3.2.1, 3.2.2 (A), 3.2.3, 3.2.4 (AA), 3.2.6 Consistent Help (A)No surprise context changes; consistent navigation and help
Errors3.3.1 (A), 3.3.2 (A), 3.3.3 (AA), 3.3.4 (AA)Errors identified in text, labels given, suggestions, reversible/confirmed legal & money actions
Re-entry & login3.3.7 Redundant Entry (A), 3.3.8 Accessible Authentication (AA)No re-typing; no puzzle-only login
Name, role, value4.1.2 (A)Every control exposes name, role, state
Status messages4.1.3 (AA)Announced without moving focus

Numbers to remember​

WhatValue
Text contrast4.5:1 (large text 3:1)
Large text≥ 24 px regular, or ≥ 18.66 px bold (18 pt / 14 pt)
Non-text contrast (controls, focus ring)3:1
Zoom200% text; reflow at 320 CSS px wide
Target size (AA)24 × 24 CSS px (AAA: 44 × 44)
Flashing≤ 3 per second
Text spacing testline-height 1.5 × font size; paragraph spacing 2 ×; letter 0.12 ×; word 0.16 ×

Manual check routine​

Per page / state:
[ ] Title describes the page; one h1; heading levels in order
[ ] Landmarks: header, nav, main, footer
[ ] Tab through everything: order, visible focus, no traps, Esc closes things
[ ] Every control: visible label = accessible name; role and state correct
[ ] Images: alt text meaningful / empty for decoration
[ ] Contrast of text, controls, focus ring
[ ] Zoom 200% and 320 px width: nothing lost or overlapping
[ ] Forms: labels, required marked in text, errors in words + linked + announced
[ ] Status messages announced (screen reader)
[ ] Motion can be paused; no flashing
[ ] Key journey completed with a screen reader

Keyboard expectations​

WidgetKeys
LinkEnter
ButtonEnter, Space
CheckboxSpace
Radio groupArrows move and select; Tab leaves the group
Select / comboboxArrows; Enter or Space opens; typing jumps
MenuArrows; Enter activates; Esc closes and returns focus
TabsArrows switch tabs; Tab moves into the panel
DialogFocus moves inside; Tab cycles inside; Esc closes; focus returns to the opener
AccordionEnter/Space toggles; aria-expanded updates

Patterns for every widget: the W3C ARIA Authoring Practices Guide (APG).

Screen-reader commands​

ActionNVDA (Windows)VoiceOver (macOS)VoiceOver (iOS)TalkBack (Android)
Start / stopCtrl+Alt+N / Insert+QCmd+F5Accessibility shortcutVolume keys shortcut (if set)
Next item↓VO+→Swipe rightSwipe right
ActivateEnterVO+SpaceDouble-tapDouble-tap
Next headingHVO+Cmd+HRotor → Headings, swipe downReading controls → Headings
Next landmarkDRotor (VO+U) → LandmarksRotor → LandmarksReading controls
List of links/headingsInsert+F7VO+URotor—
Stop speakingCtrlCtrlTwo-finger tapTwo-finger tap

VO = Ctrl+Option. Insert = the NVDA key (Caps Lock can be set instead).

ARIA patterns​

<!-- icon-only button -->
<button aria-label="Close dialog">✕</button>

<!-- error linked to a field -->
<input id="email" aria-describedby="email-error" aria-invalid="true">
<p id="email-error">Enter an email address like name@example.com</p>

<!-- disclosure / accordion -->
<button aria-expanded="false" aria-controls="details">Shipping details</button>
<div id="details" hidden>…</div>

<!-- announcements -->
<p role="status">3 results found</p>
<p role="alert">Your session will end in 1 minute</p>

<!-- dialog -->
<div role="dialog" aria-modal="true" aria-labelledby="dlg-title">
<h2 id="dlg-title">Delete item?</h2>
</div>

<!-- skip link, first thing in <body> -->
<a href="#main" class="skip-link">Skip to main content</a>

Native <dialog>, <details>/<summary>, <button> and <select> give much of this for free — prefer them.


axe tags and rules​

TagIncludes
wcag2a, wcag2aaWCAG 2.0 A / AA rules
wcag21a, wcag21aaAdded in WCAG 2.1
wcag22aaAdded in WCAG 2.2
best-practiceNot required by WCAG but recommended (landmarks, one h1…)

Common rule ids: color-contrast, image-alt, label, select-name, button-name, link-name, html-has-lang, document-title, aria-valid-attr-value, duplicate-id-aria, landmark-one-main, page-has-heading-one, region, target-size.

const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
.include('#checkout') // scan one part of the page
.exclude('.third-party-widget') // skip what you don't own (and report it separately)
.disableRules(['color-contrast']) // only with a recorded reason
.analyze();
// results.violations — failed; results.incomplete — "needs review" by a person

Playwright assertions​

Assertion / locatorChecks
getByRole('button', { name: 'Sign up' })Element has that role and accessible name
getByLabel('Email')A real label exists
toHaveAccessibleName('…')Announced name
toHaveAccessibleDescription('…')Announced description (hints, errors)
toHaveRole('dialog')Role
toBeFocused()Focus landed where expected
toHaveAttribute('aria-expanded', 'true')State
expect(page.locator('body')).toMatchAriaSnapshot(…)The accessibility tree matches an approved snapshot
page.keyboard.press('Tab') + document.activeElementFocus order

Other tools​

ToolUse
axe DevTools extensionScan a page in the browser
WAVE (WebAIM)Visual overlay of issues
Accessibility Insights (Microsoft)Guided manual assessment + FastPass
LighthouseAccessibility score (runs axe rules)
WebAIM / TPGi Colour Contrast AnalyserContrast of any two colours
Chrome DevTools → Accessibility paneName, role, accessibility tree
Pa11y / Pa11y CIScan many URLs from the command line
Android Accessibility Scanner, Xcode Accessibility InspectorMobile apps

Issue template​

ID / Title:   A11Y-07 — "Sign up" can't be reached or pressed with a keyboard
Page / state: /signup, default state
WCAG: 2.1.1 Keyboard (A); 4.1.2 Name, Role, Value (A)
Severity: Blocker — keyboard and screen-reader users can't create an account
Who: Keyboard-only users, screen-reader users, switch users
Found with: Keyboard (Tab ×5), NVDA 2025.x + Chrome
Element: <div class="btn" id="submit" onclick="submitForm()">
Fix: Use <button type="submit">Sign up</button>

Severity​

SeverityMeaning
BlockerA user group can't complete a key task (sign up, pay)
SeriousVery hard, or needs a workaround most users won't find
ModerateAnnoying or slows users down
MinorSmall; best-practice level

Need more detail? Cheat sheet · Best practices · Learning path · Full guide