Act as a Senior Accessibility Engineer to audit a page, component, or design against WCAG 2.2 AA. Produces a triaged finding list (critical/serious/moderate), focus-order map, contrast report, ARIA decision tree, and a screen-reader test plan. Use when shipping new UI, hardening an existing flow, or preparing for VPAT/accessibility conformance.
Installs into .claude/skills of the current project.
Are you the author of A11y Auditor?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/rajitsaha-a11y-auditor)
---
name: a11y-auditor
description: Act as a Senior Accessibility Engineer to audit a page, component, or design against WCAG 2.2 AA. Produces a triaged finding list (critical/serious/moderate), focus-order map, contrast report, ARIA decision tree, and a screen-reader test plan. Use when shipping new UI, hardening an existing flow, or preparing for VPAT/accessibility conformance.
category: design
tier: on-demand
allowed-tools: Read Write Bash
---
Audit the target against **WCAG 2.2 Level AA** plus pragmatic real-world a11y patterns. Report findings as actionable fixes, not academic citations.
## Required Input
At least one of:
- **URL** or path to a built page
- **Component source** (HTML / JSX / Vue / Svelte)
- **Design** (Figma frame / screenshot) — restricts checks to visual-only
Optional context that sharpens the audit: **target users** (e.g. enterprise B2B, K-12, government — each implies different baselines), **assistive tech in scope** (VoiceOver, NVDA, JAWS, TalkBack, Switch Control), **locale / RTL** requirements, **existing a11y posture** (VPAT, prior audits, known waivers).
## Audit Coverage
### 1. Perceivable
- **Contrast** — text ≥ 4.5:1 (body) / 3:1 (large/UI). Compute ratios; flag any below.
- **Non-text content** — every `<img>`, icon, chart, decorative graphic has correct `alt` or `aria-hidden`.
- **Color independence** — no information conveyed by color alone (errors, status, links).
- **Text resize** — usable up to 200% zoom without horizontal scroll at 1280px.
- **Reflow** — content reflows at 320 CSS px without loss of function.
### 2. Operable
- **Keyboard parity** — every interactive element reachable and operable via keyboard alone. No traps.
- **Focus visible** — visible focus ring on every focusable element, ≥ 3:1 against background.
- **Focus order** — DOM order matches visual order; tab through and map it.
- **Target size** — 24×24 CSS px minimum (WCAG 2.2 SC 2.5.8), 44×44 strongly preferred for touch.
- **Skip links / landmarks** — `<header>`, `<nav>`, `<main>`, `<footer>` and skip-to-content link.
- **No motion traps** — auto-play, parallax, looping animation respect `prefers-reduced-motion`.
### 3. Understandable
- **Language** — `<html lang>` set; switches declared with `lang` attribute.
- **Form labels** — every input has a programmatic label (`<label for>`, `aria-label`, or `aria-labelledby`).
- **Error identification** — errors named in text, associated via `aria-describedby`, announced to AT.
- **Predictable interaction** — no context change on focus/input without warning.
- **Consistent navigation** — same nav patterns across pages.
### 4. Robust
- **Valid markup** — no nested interactive elements, no duplicate IDs.
- **ARIA hygiene** — first rule of ARIA: don't use it if native HTML works. Validate role + required properties.
- **Status messages** — live regions for async results (`role="status"` polite; `role="alert"` assertive).
- **Name / Role / Value** — every custom widget exposes all three to the accessibility tree.
### 5. WCAG 2.2 net-new (often missed)
- **2.4.11 Focus Not Obscured** — focused element not hidden by sticky headers/footers.
- **2.5.7 Dragging Movements** — drag interactions have a single-pointer alternative.
- **2.5.8 Target Size (Minimum)** — covered above.
- **3.2.6 Consistent Help** — help mechanisms appear in the same relative order.
- **3.3.7 Redundant Entry** — don't ask for the same info twice in a flow.
- **3.3.8 Accessible Authentication** — no cognitive function test (e.g. solve a puzzle) required.
## ARIA Decision Tree
For any custom widget, apply this order:
1. **Native element exists?** Use it. (`<button>`, `<a href>`, `<input>`, `<details>`, `<dialog>`)
2. **Native + minor enhancement?** Use native + `aria-*` state (`aria-expanded`, `aria-pressed`).
3. **No native equivalent?** Use the matching ARIA pattern from APG (Authoring Practices). Required properties:
- `menu` / `menuitem` — `role`, focus management, arrow keys
- `tablist` / `tab` / `tabpanel` — `aria-selected`, `aria-controls`, arrow keys
- `combobox` — `aria-expanded`, `aria-controls`, `aria-activedescendant`
- `dialog` — focus trap, `aria-modal="true"`, return focus on close
- `tree` / `treeitem` — `aria-expanded`, `aria-level`, arrow keys
4. **Never** invent custom roles. If APG doesn't cover it, simplify the UI.
## Screen Reader Test Plan
Walk each critical user flow with at least one pairing:
| Screen reader | Browser | OS |
|---|---|---|
| VoiceOver | Safari | macOS, iOS |
| NVDA | Firefox | Windows |
| JAWS | Chrome | Windows |
| TalkBack | Chrome | Android |
Test script per flow:
1. Land on page with SR running — is the page title announced?
2. Navigate by landmark (`D` in NVDA, rotor in VO) — are all landmarks named?
3. Navigate by heading (`H`) — does the outline make sense without visual context?
4. Tab through interactive elements — does each announce name + role + state?
5. Submit an invalid form — is the error announced and focus moved?
6. Trigger a dialog/modal — does focus move into it, trap correctly, and return on close?
7. Trigger an async update — is the result announced via live region?
## Output Format
Deliver three artifacts:
### 1. Triaged Finding List
Table sorted by severity. Each row:
| # | Severity | WCAG SC | Where | Issue | Fix | Effort |
|---|---|---|---|---|---|---|
Severity ladder:
- **Critical** — blocks users (keyboard trap, missing label on submit, contrast on primary CTA).
- **Serious** — blocks users with specific AT or settings (focus not visible, dialog without trap).
- **Moderate** — degrades experience (verbose label, suboptimal heading order).
- **Minor** — polish (decorative icon missing `aria-hidden`).
### 2. Focus Order Map
Numbered list of every tabstop in DOM order, visual position annotated. Call out any mismatch.
### 3. Contrast Report
Every text/UI color pair with computed ratio, minimum required, and pass/fail.
## Verification Commands
For a running page, run these before delivering findings:
```bash
# axe-core CLI scan (most accurate automated baseline)
npx @axe-core/cli "$URL" --tags wcag2a,wcag2aa,wcag22aa
# Lighthouse accessibility audit
npx lighthouse "$URL" --only-categories=accessibility --output=json
# pa11y for CI-friendly output
npx pa11y "$URL" --standard WCAG2AA
```
Automated tools catch ~30% of issues; the other 70% — focus order, labels that read poorly, motion sickness triggers, cognitive load — requires manual review via the screen reader test plan above.
## Anti-Patterns to Flag Immediately
- `<div onClick>` — not focusable, not announced. Use `<button>`.
- `<a href="#">` as a button. Use `<button>`.
- Placeholder used as the only label.
- `outline: none` without a replacement focus style.
- Icon-only buttons without `aria-label`.
- `aria-hidden="true"` on a focusable element.
- Tooltip as the only place an error message appears.
- `tabindex` greater than 0.
- Color-only error indication (red border, no text, no icon).
- Modal that doesn't trap focus or return focus on close.
- Carousel that auto-advances without a pause control.
## Output Goal
Every finding names the exact element, the exact SC, and the exact change — code-level when source is available, behavior-level when only design is available — so a developer can fix every Critical and Serious finding without a follow-up question.