A11y
Purpose: make web content accessible. Minimum target: WCAG 2.2 Level AA.
Definitions
- Scope: the exact pages, journeys, and states you will test.
- Matrix row: one combination of route, state, viewport, and input mode.
- Evidence: a recorded result that another person can reproduce.
Workflow checklist
Copy this checklist and track your progress:
Audit Progress:
- 1. Choose the mode
- 2. Establish the boundary
- 3. Build the matrix
- 4. Capture the baseline
- 5. Triage findings
- 6. Remediate (remediate mode only)
- 7. Verify (remediate mode only)
- 8. Report
1. Choose the mode
Two modes exist. Choose one before any other step.
- Audit mode: inspect and report only. Do not change product source code.
- Remediate mode: inspect, fix, add regression coverage, and re-verify.
Audit mode executes steps 1, 2, 3, 4, 5, and 8. Remediate mode executes steps 1 through 8.
2. Establish the boundary
Record, in writing, all of the following:
- Mode: audit or remediate.
- Target surfaces: changed feature, selected routes, or representative sample.
- User tasks: the essential actions users must complete.
- Support baseline: browsers, assistive technology, and versions.
- Data constraints: authentication, test accounts, and fixtures.
- Evidence location: where results will be stored.
If the scope is ambiguous, choose a narrower scope. A narrow scope produces a true claim. A broad scope produces a false claim.
Done when: mode, scope, support baseline, constraints, and evidence location are all explicit.
3. Build the matrix
Create one row for each combination of:
- Route or journey.
- UI state: empty, loading, populated, error, authenticated, dialog, menu, toast, drag.
- Viewport: mobile, desktop, and intermediate widths.
- Input mode: keyboard, pointer, touch, screen reader.
Give every row a stable identifier, for example checkout-empty-mobile-kb.
Output the matrix table. Stop. Do not run axe until the user confirms the rows.
Done when: the user has confirmed the rows.
4. Capture the baseline
4.1 Automated checks
-
Detect the project's package manager, test runner, and browser test setup.
-
Use axe-core. WCAG 2.2 rules are disabled by default in axe-core. Enable them before the run. See
references/axe-setup.mdfor working configuration in common test stacks. -
Select the full WCAG 2.2 A/AA tag set. Each axe rule carries exactly one WCAG version and level tag, so select every tag up to the target:
runOnly: { type: "tag", values: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22a", "wcag22aa"] }The tag
wcag22acurrently matches no rules. Include it anyway. The set stays valid and future-proof. -
Run automated checks against every rendered state. Axe does not test hidden content: inactive menus, closed dialogs, and unrendered regions are skipped. Activate each state, then re-run.
-
Save the raw output per row: violations, incomplete results, tool version, browser, viewport, and state.
-
Run the manual matrix in
references/manual-audit.mdfor every applicable category.
Tool order, from best to last resort:
- Existing browser tests with an axe integration.
- Existing browser automation that can expose dynamic states.
- Project-local axe CLI or axe-core in the test stack.
- Static source inspection, only when the app cannot run. If you use it, report reduced confidence.
Lighthouse score is not evidence. Output axe violations per matrix row. Do not use Lighthouse as a substitute for axe or the manual matrix.
Done when: every row has automated evidence and applicable manual evidence, or a written reason why it cannot be tested.
4.2 Manual checks
Load references/manual-audit.md. For every matrix row, mark each category
Applicable or N/A. Do not force irrelevant work. Complete every check
in each applicable category, or record why it cannot be tested. Record the
exact browser, operating system, assistive technology, and version for all
screen-reader evidence.
5. Triage findings
Prioritize in this order:
- Blocks an essential task.
- Appears on shared surfaces: layout, navigation, forms.
- Confirmed WCAG A or AA violation.
- User impact.
- Confidence.
- Fix leverage versus regression risk.
For every finding, record:
- Affected matrix rows.
- User consequence.
- Evidence.
- The WCAG criterion.
- Confidence.
- Proposed fix.
- Verification method.
Audit mode: continue to step 8. Do not fix code.
6. Remediate
- Fix root causes in small batches. Verify after each batch.
- Prefer native HTML, visible labels, and established project primitives.
- Treat every ARIA role as a contract for keyboard and focus behavior.
- Keep all rules enabled. If you disable a rule, record the reason and its impact on the claim.
- Add regression tests in the existing test stack.
Done when: every confirmed in-scope A/AA failure and critical task barrier is fixed, or explicitly deferred with a reason and evidence.
7. Verify
-
Re-run the identical matrix.
-
Compare before and after evidence with
scripts/compare-evidence.mjs:node scripts/compare-evidence.mjs before.json after.jsonThe script exits 1 if any finding was added. That is the intended behavior.
-
Inspect every new and every incomplete result.
-
Exercise essential journeys with keyboard and with each declared browser and assistive-technology combination.
-
Record remaining limitations.
Done when: no unexplained mismatch remains, and manual checks and project tests pass.
8. Report
Use this exact template:
Accessibility report: <scope>
Mode and scope
- Mode: <audit | remediate>
- Surfaces: <target surfaces>
- Matrix: <N rows, identifier range>
Environment
- Browsers: <names and versions>
- Assistive technology: <names and versions>
- Tools: <axe-core version and other tools>
Findings
| # | Severity | WCAG SC | Location | User impact | Evidence | Status |
|---|---|---|---|---|---|---|
| 1 | critical | 2.5.8 | path:line | <consequence> | <evidence> | fixed / deferred |
Evidence
- <per-row before/after summary>
- Raw output: <location>
Risks and exclusions
- <unresolved risks>
- <deferrals with reason and evidence>
Claim limits
- <what was tested and what was not>
Rules for claims:
- "Axe zero" is an instrument reading, not conformance.
- "Lighthouse 100" is an instrument reading, not conformance.
- Claim only what you tested: surfaces, states, environments, and methods.