A11y Compliance Skill
Integrate WCAG 2.2 accessibility audits into the local development cycle using @axe-core/cli.
Step 0 — Confirm Dev Server with Operator
YOU MUST ask the operator (the developer running this session) before scanning:
Before I run the audit, please confirm:
1. Is the dev server running locally?
2. What is the URL and port? (e.g. http://localhost:3000)
3. Which routes/pages should I audit? (list them, or say "homepage only")
Do NOT proceed to Step 1 until the operator confirms the server is up and provides the URL. Never assume a default port.
Step 1 — Audit
Run the scan using the URL and routes confirmed by the operator.
npx @axe-core/cli http://localhost:PORT \
--tags wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22aa \
--save a11y-report.json \
--exit \
--chrome-options="no-sandbox,disable-dev-shm-usage" \
--load-delay 1500
Multiple routes (not a crawler — list each explicitly):
npx @axe-core/cli \
http://localhost:PORT \
http://localhost:PORT/about \
http://localhost:PORT/contact \
--tags wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22aa \
--dir ./a11y-reports \
--exit \
--chrome-options="no-sandbox,disable-dev-shm-usage" \
--load-delay 1500
Replace PORT with the actual port (3000, 5173, 4000, etc.). If unsure, check package.json scripts.
SPA / React / Vue / Next.js: increase --load-delay to 2000–3000 if results look incomplete.
Step 2 — Parse the Report
Read a11y-report.json. Focus on the violations array. Ignore passes and inapplicable.
{
"violations": [
{
"id": "color-contrast",
"impact": "serious",
"description": "Elements must have sufficient color contrast",
"helpUrl": "https://dequeuniversity.com/rules/...",
"tags": ["wcag2aa", "wcag21aa"],
"nodes": [
{
"html": "<p class=\"subtitle\">...</p>",
"target": [".subtitle"],
"failureSummary": "Fix any of: Element has insufficient color contrast..."
}
]
}
],
"incomplete": [...],
"passes": [...],
"inapplicable": [...]
}
Key fields per violation:
impact— priority:critical>serious>moderate>minornodes[].html— the exact element to fixnodes[].target— CSS selector to locate it in sourcefailureSummary— what specifically failed and what to do
Step 3 — Fix Violations
Work through violations grouped by impact. For each node:
- Use
nodes[].target(CSS selector) to locate the element in source files - Apply the fix described in
failureSummary - Do NOT guess — reference
helpUrlfor the WCAG rule if intent is unclear
Common fixes by rule ID:
| Rule ID | Fix |
|---|---|
color-contrast |
Increase contrast ratio to ≥ 4.5:1 (text) or ≥ 3:1 (large text/UI) |
image-alt |
Add descriptive alt attribute to <img> |
label |
Associate <label for="id"> with every form input |
html-has-lang |
Add lang="en" (or correct locale) to <html> tag |
button-name |
Add visible text or aria-label to every <button> |
link-name |
Add descriptive text or aria-label to every <a> |
heading-order |
Fix heading hierarchy (no skipping h1→h3) |
landmark-one-main |
Wrap main content in <main> |
region |
Wrap all content in landmark regions (<header>, <main>, <footer>, <nav>) |
focus-visible |
Ensure visible focus ring on all interactive elements |
aria-required-attr |
Add missing required ARIA attributes |
duplicate-id |
Ensure all id attributes are unique per page |
Step 4 — Verify
Re-run the exact same audit command after fixing:
npx @axe-core/cli http://localhost:PORT \
--tags wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22aa \
--save a11y-report-after.json \
--exit \
--chrome-options="no-sandbox,disable-dev-shm-usage" \
--load-delay 1500
Pass = zero entries in violations. --exit will return code 0.
If new violations appear that were not in the original report, you introduced a regression. Fix before proceeding.
Step 5 — Report Incompletes
For every item in incomplete, YOU MUST create a clearly worded note — do NOT auto-fix:
⚠️ NEEDS HUMAN REVIEW
Rule: {id}
Element: {nodes[].html}
Reason: axe-core could not determine compliance automatically.
Action: Manual test required — {failureSummary}
Incompletes require manual keyboard testing, screen reader validation, or visual inspection.
Tag Reference
| Tag | Standard |
|---|---|
wcag2a |
WCAG 2.0 Level A |
wcag2aa |
WCAG 2.0 Level AA |
wcag21a |
WCAG 2.1 Level A |
wcag21aa |
WCAG 2.1 Level AA |
wcag22aa |
WCAG 2.2 Level AA |
best-practice |
Deque best practices (optional, non-normative) |
YOU MUST include all five WCAG tags. Stricter rulesets do NOT inherit looser ones — omitting any tag silently skips those rules.
Scope Flags (optional)
--include "main" # Scan only the <main> element and its children
--exclude ".third-party" # Skip known third-party widgets you don't own
--rules color-contrast # Run only specific rule(s) for targeted fixes
--disable duplicate-id # Skip a specific rule (use sparingly)