WCAG 2.2
wcag 2.2 wcag 2.2 css conformance maps w3c success criteria to concrete stylesheet decisions — focus visibility, target size, contrast,
Introduction
WCAG 2.2 CSS conformance maps W3C success criteria to concrete stylesheet decisions — focus visibility, target size, contrast, motion, reflow, and non-color state. Staff engineers treat CSS as part of the accessibility contract: a component is not shippable until its styles pass automated rules and manual keyboard/screen-reader validation.
Business problem
Legal and revenue risk: EU Accessibility Act (2025), ADA, and AODA enforcement target visual polish that fails WCAG 2.2 — invisible focus rings, 44×44px touch targets, drag-only interactions styled without keyboard alternatives.
- Procurement: B2G contracts require WCAG 2.2 AA attestation backed by test evidence.
- Brand: Public a11y failures on checkout or auth flows generate press and social backlash beyond lawsuit cost.
- Quality: CSS that breaks zoom (1.4.4) or reflow (1.4.10) fails real users on mobile — not just audit tools.
Why this feature exists
WCAG 2.2 (September 2023) adds criteria that CSS directly controls: Focus Not Obscured (2.4.11/2.4.12), Target Size Minimum (2.5.8), Dragging Movements (2.5.7), and Accessible Authentication (3.3.8). CSS cannot fix bad semantics alone, but it can violate criteria without a single line of JavaScript.
- POUR: Perceivable (contrast, motion), Operable (focus, target size), Understandable (consistent focus), Robust (works with AT + zoom).
- AA baseline: Most regulations reference Level AA — not AAA sitewide.
- ACT rules: Standardized automated tests map CSS properties to criteria IDs.
Browser rendering perspective
CSS affects the accessibility tree indirectly: `display:none`, `visibility:hidden`, `content-visibility`, and `aria-hidden` (HTML) remove or expose nodes. `:focus-visible` styles determine whether keyboard users can see focus (2.4.7). High contrast mode and forced-colors media query override author styles — design must degrade gracefully.
- Blink: Focus ring drawn via outline or `:-webkit-focus-ring-color` heuristics when author removes outline.
- Gecko: `:-moz-focusring` and forced-colors palette substitution.
- WebKit: Safari 17+ improved `:focus-visible` parity — still test iOS VoiceOver + keyboard.
Internal browser workflow
Conformance workflow: Map each UI pattern to WCAG criteria → encode CSS tokens (focus, contrast, motion) → run axe/Lighthouse on rendered pages → manual keyboard + SR spot-check → document exceptions in ACR.
- Design tokens: `--focus-ring`, `--min-target-size: 44px`, `--motion-safe` variants.
- Component DoD: Zero critical axe violations; focus visible; 200% zoom reflow.
- 2.2 deltas: Audit modals for focus obscured by sticky headers; audit drag sliders for keyboard alternative.
Feature deep dive
WCAG 2.2 criteria with direct CSS ownership:
- 1.4.3 / 1.4.11: Text and UI component contrast — token pipeline enforces 4.5:1 / 3:1.
- 1.4.4 / 1.4.10: Resize text 200%; reflow without horizontal scroll — avoid fixed px widths.
- 2.4.7 / 2.4.11: Focus visible; focus not obscured by sticky/fixed overlays.
- 2.5.8: Target size minimum 24×24 CSS px (AA) — prefer 44×44 for touch.
- 2.3.3: `prefers-reduced-motion: reduce` disables non-essential animation.
:root {--focus-ring: 2px solid #2563eb;--focus-offset: 2px;--min-target: 44px;}:focus-visible {outline: var(--focus-ring);outline-offset: var(--focus-offset);}@media (prefers-reduced-motion: reduce) {*, *::before, *::after {animation-duration: 0.01ms !important;transition-duration: 0.01ms !important;}}
Syntax
CSS techniques for WCAG 2.2 AA:
/* Focus not obscured — reserve space for sticky header */:root { --header-h: 64px; }:focus-visible { scroll-margin-top: var(--header-h); }/* Target size — icon buttons */.icon-btn {min-width: var(--min-target);min-height: var(--min-target);display: inline-flex;align-items: center;justify-content: center;}/* Forced colors / high contrast */@media (forced-colors: active) {.btn { border: 2px solid ButtonText; }}
Examples
Modal focus obscured fix: Sticky header with `z-index: 100` covers focused link inside dialog — add `scroll-margin` on focusable elements and ensure dialog `z-index` stacks above chrome.
.dialog[open] { z-index: 200; }.dialog :focus-visible { scroll-margin: 80px 0; }
Real-world use
Industry practice: GOV.UK Design System, USWDS, and Carbon publish WCAG-mapped CSS for focus, spacing, and motion. Microsoft Fluent documents forced-colors behavior. EU public sector procurement references EN 301 549 which incorporates WCAG 2.2.
Real production example
Design token gate in CI: Style Dictionary exports contrast pairs; custom lint rejects `outline: none` without `:focus-visible` replacement.
- axe-core: color-contrast, target-size, focus-order rules on Storybook + PR previews.
- VPAT: Map token names to WCAG criteria in accessibility statement.
/* stylelint-a11y / eslint-plugin-jsx-a11y companion rules *//* Ban: .btn:focus { outline: none; } without :focus-visible block */
Enterprise use case
Enterprise design systems ship WCAG 2.2 checklists per component: Button, Link, Modal, Tabs — each documents CSS requirements and known browser exceptions.
- Legal hold: Audit logs tie release SHA to axe report artifacts.
- Training: Designers use contrast-approved Figma styles only — no ad-hoc hex outside tokens.
Accessibility considerations
This lesson is accessibility. CSS is the enforcement layer for visual WCAG criteria — staff engineers own token contracts, not one-off fixes before launch.
- Never: `outline: none` globally; color-only error states; `pointer-events: none` on interactive-looking elements.
- Always: `:focus-visible`; text spacing overrides (1.4.12) respected; motion preferences honored.
Performance considerations
Reduced motion and containment can improve perf — `prefers-reduced-motion` often correlates with users on low-end devices. Avoid expensive blur on focus rings; use solid outline.
- CLS: Focus ring outline-offset shouldn't shift layout — use outline not border width change.
SEO considerations
Overlap: Readable contrast and reflow improve mobile usability scores in Lighthouse — a ranking signal via Core Web Vitals adjacent checks.
- Tap targets: Google mobile-friendly audit aligns with WCAG target size guidance.
Scalability considerations
Multi-brand tokens: Each white-label theme must re-validate contrast pairs — automated diff on token export prevents one tenant shipping 3.8:1 gray-on-gray.
- Dark mode: Separate contrast matrix per theme — dark gray text on dark gray bg is a common regression.
Common production issues
Incidents: Global `outline: none` in CSS reset broke keyboard nav sitewide. Sticky promo banner covered focused checkout field — 2.4.11 failure. Animation ignored `prefers-reduced-motion` — vestibular disorder complaints.
- Fix pattern: Reset `:focus-visible` in design system base layer; never in product overrides.
Debugging guide
Debug WCAG CSS failures: Chrome DevTools → Rendering → Emulate forced colors; Accessibility pane shows contrast ratio; axe DevTools lists criterion IDs.
- Zoom test: 200% browser zoom + 320px viewport — horizontal scroll indicates 1.4.10 fail.
- Focus test: Tab through page recording video — verify ring visible on every interactive element.
Best practices
- Encode WCAG requirements as design tokens — focus, contrast, target size, motion.
- Use :focus-visible, not :focus, for pointer vs keyboard differentiation.
- Test forced-colors and prefers-reduced-motion in CI story snapshots.
- Document WCAG criterion ID per component in design system docs.
- Block PR merge on critical axe color-contrast and target-size violations.
Anti-patterns
- outline: none on * { } reset without :focus-visible replacement.
- Using only :hover styles for critical state — no :focus or aria state styling.
- Fixed font-size px preventing user text resize (1.4.4).
- position:fixed cookie banners covering focused elements without scroll-margin.
Trade-offs
- Benefit: Tokenized WCAG CSS prevents audit fire drills before launch.
- Benefit: Legal defensibility with automated + manual test artifacts.
- Cost: Stricter palette reduces designer freedom — governance required.
- Cost: 44px targets increase density trade-offs on mobile toolbars.
- Risk if skipped: Retrofit cost 10× vs building tokens from sprint one.
Architecture review questions
- Does every interactive component have visible :focus-visible styles?
- Are all text/UI contrast pairs validated at AA in both light and dark themes?
- Does 200% zoom reflow without two-axis scrolling on primary flows?
- Are animations gated behind prefers-reduced-motion?
- Do sticky/fixed elements obscure focused controls (2.4.11)?
Interview questions
Which WCAG 2.2 criteria are primarily CSS-owned?(Advanced)
Contrast (1.4.3/11), resize/reflow (1.4.4/10), focus visible (2.4.7), focus not obscured (2.4.11/12), target size (2.5.8), reduced motion (2.3.3). HTML owns semantics; CSS owns visual operability and perceivability.
Follow-up: How do you enforce contrast at scale?
Why is outline:none dangerous and what's the fix?(Intermediate)
It removes the native focus indicator keyboard users require (2.4.7). Fix: never global none; use :focus-visible with high-contrast outline/box-shadow token; ensure 3:1 contrast against adjacent colors.
Follow-up: Does box-shadow focus ring affect layout?
Explain focus not obscured in a modal with sticky header.(Advanced)
When focus moves to a control near the top of the modal, sticky site header must not cover it. Use scroll-margin on :focus-visible, raise modal z-index above chrome, or shrink sticky header when dialog open via :has(.dialog[open]).
Follow-up: 2.4.11 vs 2.4.12 difference?
Hands-on exercise
Exercise: Audit a button component CSS against WCAG 2.2 AA — add :focus-visible token, 44px min target, forced-colors border, reduced-motion transition off. Pass axe zero critical on three themes.
- Document criterion ID per CSS change in PR.
- Record keyboard tab video through component states.
Staff engineer notes
- WCAG 2.2 AA is the enterprise default — map criteria to tokens, not wiki pages.
- Forced-colors mode breaks gradient buttons — always provide border fallback.
- Legal cares about test evidence — axe JSON artifacts per release, not screenshots alone.
Common pitfalls
- Assuming Safari :focus-visible matches Chrome without device testing.
- Checking contrast only on primary button — missing disabled/placeholder states.
- Using vw-only typography that fails 200% zoom combined with browser text sizing.
Try it yourself
Edit the CSS panel — the preview updates live. Use DevTools Performance and Accessibility panels to validate.
Try it yourself
Summary
WCAG 2.2 CSS conformance encodes accessibility requirements in design tokens and component styles — focus visibility, contrast, target size, motion, and reflow — enforced by axe/Lighthouse in CI and validated with keyboard and screen reader testing.
Key takeaways
- WCAG 2.2 AA maps directly to CSS tokens: focus, contrast, target size, motion, reflow.
- Use :focus-visible and prefers-reduced-motion — never global outline removal.
- Automate with axe; validate zoom, forced-colors, and keyboard manually.