Accessibility Testing
accessibility testing css accessibility testing with lighthouse and axe-core forms the automated backbone of enterprise a11y programs — catching contrast,
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:
// playwright.a11y.spec.tsimport { 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:
.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
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.