CSS Tutorial 0/203 lessons ~6 min read Lesson 151

    Accessibility Testing

    accessibility testing css accessibility testing with lighthouse and axe-core forms the automated backbone of enterprise a11y programs — catching contrast,

    Course progress0%
    Focus
    27 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    CSS accessibility testing with Lighthouse and axe-core forms the automated backbone of enterprise a11y programs — catching contrast, target size, focus, and ARIA presentation issues on every build. Staff engineers combine these tools with manual keyboard and screen reader passes for WCAG 2.2 AA sign-off.

    Business problem

    Without automated CSS testing, contrast and focus regressions ship weekly — manual QA cannot diff 400 components × 3 themes. Legal demands continuous evidence; Lighthouse and axe provide machine-readable artifacts.

    • Scale: Design system teams gate publish on axe zero critical across stories.
    • Speed: Lighthouse CI on PR — minutes vs weeks for manual-only.

    Why this feature exists

    axe-core (Deque) implements WCAG rules including color-contrast, target-size, focus-order. Lighthouse (Google) bundles axe plus audits for tap targets and best practices — useful score trend for leadership dashboards.

    • @axe-core/playwright: Integration standard for E2E CSS testing on rendered pages.
    • lighthouse-ci: Assert accessibility category min score in GitHub Actions.
    • Limit: ~50% max coverage — manual SR/keyboard mandatory.

    Browser rendering perspective

    Tests run against computed styles after CSS cascade — including media queries, dark mode class, and @media (prefers-color-scheme). Test all theme permutations.

    • Font loading: FOIT can change contrast — wait for networkidle or webfont load in Playwright.

    Internal browser workflow

    Full test stack: 1) stylelint + contrast matrix 2) axe Storybook 3) axe-playwright on routes 4) Lighthouse CI 5) manual NVDA/VoiceOver 6) store JSON artifacts per release.

    Feature deep dive

    Lighthouse + axe integration:

    css
    // playwright.a11y.spec.ts
    import { test, expect } from "@playwright/test";
    import AxeBuilder from "@axe-core/playwright";
    test("checkout meets WCAG 2.2 AA css rules", async ({ page }) => {
    await page.goto("/checkout");
    await page.emulateMedia({ colorScheme: "dark" });
    const results = await new AxeBuilder({ page })
    .withTags(["wcag2aa", "wcag22aa"])
    .analyze();
    expect(results.violations.filter(v => v.impact === "critical")).toEqual([]);
    });
    // lighthouse-ci assert accessibility >= 0.95

    Syntax

    axe rule tags for CSS-heavy criteria:

    css
    .withTags(["wcag2aa", "wcag22aa", "best-practice"])
    // Key rules: color-contrast, target-size, focus-order, scrollable-region-focusable

    Examples

    PR check: Comment bot lists axe violations with selector, helpUrl linking to deque docs, and failing HTML snippet — engineer fixes CSS token.

    Real-world use

    Microsoft, Google, Salesforce contribute to axe-core rules. Lighthouse powers PageSpeed Insights accessibility section — same engine as CI.

    Real production example

    Monorepo: Shared @org/a11y-config exports axe tags and Lighthouse thresholds; each app imports in playwright.config and lighthouserc.js.

    • Artifact: Upload axe-results.json + lighthouse HTML to S3 per build ID.

    Enterprise use case

    Release gate: No production deploy if critical axe violations increased vs baseline on critical path URLs.

    Accessibility considerations

    Test states CSS cares about: default, hover, focus-visible, disabled, error, loading skeleton — Storybook stories per state.

    Performance considerations

    Parallelize Lighthouse runs across URLs in CI matrix; cache Chromium between axe scans.

    SEO considerations

    Lighthouse accessibility bundled with SEO category in PSI — shared CI job economical.

    Scalability considerations

    Baseline diff strategy — legacy 200 violations tracked; block only new ones until burn-down complete.

    Common production issues

    False confidence: Team shipped Lighthouse 100 using aria-hidden on half the page to silence axe — manual SR caught missing content.

    Debugging guide

    axe rule id → deque rule page → fix technique. Lighthouse "Additional items to manually check" lists what automation missed.

    • color-contrast: Fix token not local override.

    Best practices

    • Use axe-playwright on production build with all themes.
    • Set Lighthouse CI accessibility minScore 0.95 on critical URLs.
    • Tag tests wcag22aa for new 2.2 rules.
    • Store axe JSON artifacts per git SHA.
    • Schedule manual SR/keyboard quarterly minimum.
    • Never disable axe rules to greenwash — fix root cause.

    Anti-patterns

    • aria-hidden to silence axe violations.
    • Testing dev server unminified CSS only.
    • Lighthouse score as only compliance metric.
    • Skipping dark mode in automated CSS tests.

    Trade-offs

    • Benefit: Lighthouse + axe catch most CSS WCAG failures cheaply.
    • Cost: CI time, flake tuning, baseline maintenance.
    • Gap: Manual testing still required for legal defensibility.

    Architecture review questions

    • axe-playwright running on PR for changed routes?
    • Lighthouse CI accessibility threshold enforced?
    • Dark and light themes both scanned?
    • Manual keyboard/SR on release checklist?
    • Artifacts retained for compliance audits?

    Interview questions

    Lighthouse vs axe — when use each for CSS a11y?(Advanced)

    axe gives criterion-level violations with selectors — engineer actionable. Lighthouse gives category score + subset of axe rules — good for trends and PSI. Use both: axe for PR gates, Lighthouse for dashboard and CWV adjacent audits.

    Follow-up: What can't either tool catch?

    Design CI gate for design system CSS components.(Advanced)

    axe every Storybook story × themes × states; contrast matrix on tokens; stylelint ban outline:none; block package publish on critical; sample integration test on consumer app route.

    Follow-up: Handle flaky contrast on webfont load?

    Hands-on exercise

    Exercise: Wire @axe-core/playwright + lighthouse-ci on sample app; break contrast; fix; achieve zero critical axe + Lighthouse a11y ≥ 0.95.

    • Export axe JSON artifact.
    • List 3 issues only manual testing finds.

    Staff engineer notes

    • axe violations are tickets — Lighthouse score is executive summary.
    • Test the CSS that ships — production build, all color schemes.

    Common pitfalls

    • Running axe before SPA route hydration completes.
    • Ignoring wcag22aa tag — miss focus-not-obscured heuristics.

    Try it yourself

    Edit the CSS panel — the preview updates live. Use DevTools Performance and Accessibility panels to validate.

    Try it yourself

    Preview

    Summary

    CSS accessibility testing combines axe-core and Lighthouse in CI — Playwright scans on rendered themes and routes, contrast token lint at build, artifacts for compliance — supplemented by mandatory manual keyboard and screen reader validation.

    Key takeaways

    • Automate CSS a11y with axe-core and Lighthouse CI on production builds.
    • Test all themes and component states; diff violations vs baseline.
    • Complement automation with manual keyboard and screen reader testing.
    Ready to mark this lesson complete?Track your journey across the entire course.