Departments / qa / accessibility-audit

accessibility-audit

Use when a page or flow needs a WCAG 2.1 AA conformance audit. Runs axe-core against the live DOM via Chrome DevTools MCP, inspects the accessibility tree, verifies keyboard navigation and focus order, checks color contrast, ARIA roles, landmarks, headings, form labels, skip links, and alt text — and reports every violation with a code-level fix suggestion.

Department

QA

Safety

safe
Safe · read-only

Supported stacks

Stack-agnostic — no detection required.

When to use

Invoke this skill when:

Do NOT use when: the check can be automated inline in an e2e test (use e2e-test-generator and embed axe); the request is a full manual audit by a certified auditor (this skill assists, does not replace).

Inputs

Outputs

Tool dependencies

Procedure

  1. Open page with cookie. Navigate, set auth_cookie if provided.
  2. Inject axe-core. Via evaluate_script, load axe from a CDN (https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.10.0/axe.min.js) and run axe.run({ runOnly: { type: 'tag', values: <axe_tags> } }).
  3. Collect accessibility tree. take_snapshot to capture the a11y tree; confirm landmarks (banner, navigation, main, complementary, contentinfo) are present.
  4. Heading outline. evaluate_script to collect h1..h6 in DOM order; verify exactly one h1, no skipped levels.
  5. Form labels. For each input, textarea, select — verify id matches a <label for> or has aria-label/aria-labelledby.
  6. Alt text. For each <img> — require alt (empty for decorative, descriptive otherwise). Flag alt="image" / alt="picture" / filename-as-alt.
  7. Skip link. The first focusable element on load should link to #main (or the main landmark). If absent, flag.
  8. Keyboard walk. Send Tab 20 times via press_key; record each focused element via evaluate_script(document.activeElement). Verify:
    • Focus is always visible (outline not removed without replacement).
    • No keyboard trap (Shift+Tab reverses cleanly).
    • Tab order matches visual order.
  9. Contrast. Axe reports contrast; cross-check any visual components using getComputedStyle + WCAG formula. Required: 4.5:1 for body text, 3:1 for large text (>=18pt or >=14pt bold), 3:1 for UI component and graphical object boundaries.
  10. ARIA roles. Flag invalid combinations (role="button" on an actual <button>, aria-hidden="true" on a focusable element, redundant roles on native semantics).
  11. Write report. One Markdown file under reports/a11y/<yyyy-mm-dd>-<host>-<path>.md.

Examples

Example 1 — Sign-up form audit (desktop)

Input:

{ "url": "https://staging.example.com/signup" }

Report (excerpt):

# Accessibility audit — /signup (desktop 1366x768)
WCAG 2.1 AA, axe-core 4.10.0, 2026-04-19

## Summary
Critical: 1 | Serious: 3 | Moderate: 2 | Minor: 1

## Violations

### [critical] label — Form element has no accessible name  (WCAG 1.3.1, 4.1.2)
Selector: `form[data-testid=signup] > input[name=password]`
Failure: no <label for="password">, no aria-label, no aria-labelledby.
Fix:
```html
<label for="signup-password">Password</label>
<input id="signup-password" name="password" type="password" autocomplete="new-password">

[serious] color-contrast — 3.1:1 on placeholder text (WCAG 1.4.3)

Selector: input[name=email]::placeholder Measured: #9a9a9a on #ffffff = 2.85:1. Required: 4.5:1. Fix: change placeholder color to #595959 (ratio 7.0:1) or remove placeholder and rely on label only.

[serious] heading-order — heading levels skip from h1 to h3 (WCAG 1.3.1)

Selector: h3.signup-legal Fix: change to <h2> or wrap content under a proper h2 section.

Selector: footer a.icon-twitter Fix: add aria-label="Twitter" or a visually-hidden span.

Keyboard walk

Tab 1: skip link (visible on focus) OK Tab 2: signup-email OK Tab 3: signup-password OK — but focus outline removed (see next) Tab 4: signup-submit FAIL: outline: none; no replacement focus style.

Headings

h1: “Create your account” h3: “Terms and privacy” (missing h2)

Landmarks

banner, main, contentinfo OK navigation missing (consider adding a skip link target)


### Example 2 — Dashboard widget audit (mobile)

Input:
```json
{
  "url": "https://app.example.com/dashboard",
  "viewport": { "width": 375, "height": 667 },
  "auth_cookie": "session=abc; Domain=.example.com; Path=/",
  "include_selectors": ["[data-testid=kpi-widget]"]
}

Checks unique to mobile:

Expected output includes touch-target violations for icon-only buttons smaller than 24x24.

Constraints

Quality checks

Customise for your organisation

accessibility-audit

The LLM will rewrite this skill for your environment. Your API key and form inputs stay in your browser — only the skill and your environment go to OpenRouter.

One line. Be specific — cloud, language, framework, orchestrator.

Free text that steers the rewrite. Leave blank if nothing specific.

cost estimate: