Snippets / Accessibility /

Accessible Contrast Pair

Building color pairs that meet WCAG AA (4.5:1 for body, 3:1 for large text) and AAA (7:1) using predictable oklch() lightness values.

AA pass — body text (≥ 4.5:1) ~8.1:1
AA Large — bold UI (≥ 3:1) ~4.2:1
AAA pass — enhanced (≥ 7:1) ~14:1
Insufficient contrast — avoid ~2.1:1
Widely Supported
a11yno-js

Quick implementation

/* WCAG AA: body text — contrast ratio ≥ 4.5:1 */
/* Rule of thumb: lightness difference ≥ 0.55 in oklch */
.text-on-dark {
  background: oklch(0.18 0.02 260); /* L=0.18 dark bg */
  color: oklch(0.93 0.01 260);      /* L=0.93 light text */
}

/* WCAG AA Large: bold text / UI components — ratio ≥ 3:1 */
/* Lightness difference ≥ 0.40 in oklch */
.badge {
  background: oklch(0.35 0.18 265); /* medium accent bg */
  color: oklch(0.97 0.01 265);      /* near-white text */
  font-weight: 600;
  font-size: 0.875rem;
}

/* WCAG AAA: enhanced — ratio ≥ 7:1 */
.high-contrast-text {
  background: oklch(0.10 0.01 260); /* very dark bg */
  color: oklch(0.97 0.01 260);      /* near-white text */
}

/* Never use medium-on-medium — fails at all levels */
/* oklch(0.60 ...) text on oklch(0.45 ...) bg = ~2:1 — FAIL */

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are an accessibility-focused CSS developer. Generate color pairs using oklch() that meet WCAG contrast ratios.

Requirements:
1. Show three contrast levels: AA body text (≥ 4.5:1), AA Large for bold/large text (≥ 3:1), and AAA enhanced (≥ 7:1).
2. Use oklch() for all colors. Explain the heuristic: in oklch, a lightness (L) difference of ~0.55 between foreground and background typically achieves AA; ~0.75 achieves AAA.
3. Show one failing example (~2:1) to illustrate what to avoid — medium chroma on medium chroma.
4. All pairs should share the same hue (e.g. 265 = blue-violet) to show how lightness alone drives contrast.
5. Include a note: oklch L values are perceptually uniform, so L=0.90 text on L=0.20 bg will look evenly contrasted at every hue — unlike HSL where yellow at L=50% looks brighter than blue at L=50%.

Constraints:
- Do not use hex or rgb() — use oklch() throughout.
- Do not rely on browser DevTools contrast checker — verify programmatically with the relative luminance formula.
- Label each swatch with its approximate ratio and WCAG level.

Output HTML + CSS demonstrating all four swatches in a column layout.

Why this matters in 2026

WCAG 2.2 AA compliance is a legal requirement in many jurisdictions and a baseline expectation for any professional web project. The oklch() color space makes compliance easier to reason about because its L component is perceptually uniform — a given lightness difference produces approximately the same contrast regardless of hue. This means you can build a design token system around predictable lightness values rather than manually checking every color pair with an external tool.

The logic

WCAG contrast is calculated from relative luminance, which correlates closely — but not identically — with the L component in oklch. As a practical rule: a lightness difference of ≥ 0.55 in oklch usually achieves the 4.5:1 AA threshold for body text; ≥ 0.40 achieves the 3:1 AA Large threshold; ≥ 0.70 achieves the 7:1 AAA threshold. These are heuristics — always verify with a contrast checker for production colors, especially at high chroma values where the relationship between perceived brightness and WCAG luminance can diverge slightly.

Accessibility & performance

Contrast ratios apply to text against its direct background — not text against the page background if it sits on a card. Always measure the actual rendered pair. For disabled UI elements, WCAG 1.4.3 explicitly exempts inactive components from contrast requirements, but consider providing at least 3:1 for users with low vision who may still interact with those elements via assistive technology. There is zero performance impact: color calculation happens at paint time, already part of the rendering pipeline.