Contrast Lab
Drop in any two colors, see exactly which WCAG bars they clear, and get the nearest readable fix — computed by walking lightness in OKLCH.
The contrast meter
Large heading text
Normal body copy at a typical reading size. If you can read this comfortably, the ratio is doing its job.
Fine print and captions live down here — the first thing to disappear when contrast is too low.
bordered UI elementThe nearest fix
Pick the bar you need to clear. The lab holds each color's hue and chroma fixed and walks its lightness in OKLCH — the perceptually even axis — until the ratio passes, returning the smallest change that gets you there. One route recolors the text, the other recolors the background; take whichever fits.
This pair already clears Normal text AA (6.09:1 ≥ 4.5). Nothing to fix — raise the bar to push it further.
Readable is a number
"Is this text readable?" feels like a matter of taste. It isn't — at least not the part that matters most. The Web Content Accessibility Guidelines pin it to a single number: the contrast ratio between text and its background, somewhere between 1:1 (the same color, invisible) and 21:1 (pure black on pure white).
The tool above takes any two colors and gives you that number, the live preview, and a pass/fail grid for every WCAG bar at once. Then it does the harder thing: it hands you the nearest color that would pass.
Type a hex, drag the picker, or click an example. The "muted trap" preset is the one to study — a soft gray on dark that looks tasteful and fails almost everything.
What the ratio actually measures
The formula is older and simpler than it looks. Each color is reduced to its relative luminance — how much light it emits, with green weighted heaviest (0.2126·R + 0.7152·G + 0.0722·B, after undoing the sRGB gamma curve), because the eye is most sensitive to green. The ratio is then:
(L_lighter + 0.05) / (L_darker + 0.05)
The + 0.05 is a nod to reality: screens are never viewed in a perfectly dark room, so a little ambient flare is baked in. That single term is why even black-on-black is 1:1 and not a division by zero.
Note what the formula ignores: hue. Two colors can be wildly different — a vivid red and a vivid green — and still sit at nearly the same luminance, scoring a miserable ratio despite looking nothing alike. Contrast is about light and dark, not about color difference. That surprises people, and it's the single most common reason a "colorful" design fails an audit.
The bars, and which one you need
WCAG sets the thresholds by how hard the text is to resolve:
- 4.5:1 — normal body text, AA. The bar almost every project is actually held to.
- 3:1 — large text (≥ 18pt, or ≥ 14pt bold), AA. Bigger strokes need less contrast.
- 3:1 — UI components and graphics: borders, icons, focus rings, chart lines. Added in WCAG 2.1, and the one designers forget.
- 7:1 and 4.5:1 — the AAA tiers for normal and large text: enhanced contrast for when readability is non-negotiable.
The grid checks all five simultaneously, so you can see at a glance that a color might be fine for a heading and illegal for body copy.
The fix: nudge lightness, nothing else
Failing the check is easy. Fixing it without wrecking the design is the part tools usually skip. Crank a color toward black or white in RGB and you don't just change its brightness — you desaturate it, shift its hue, turn your brand teal into a muddy gray.
So the lab repairs colors in OKLCH, the same perceptual space the palette generator is built on. It decomposes the color you're adjusting into Lightness, Chroma, and Hue, then holds chroma and hue fixed and walks only L — the perceptually even lightness axis — until the ratio clears the bar you picked. Because moving a color's lightness away from the other color's luminance only ever raises contrast, the first L that passes in each direction is the smallest possible change: the nearest readable color, not just a readable one.
It offers two routes — recolor the text or recolor the background — because which one is "right" depends on what you're allowed to touch. Apply either and the meter updates instantly.
This is the inverse of what the palette drop needed. That one only ever went OKLCH → sRGB → hex. To nudge an existing hex, the lab adds the missing direction — hex → linear sRGB → OKLab → OKLCH — mirroring Björn Ottosson's matrices the other way. With both halves, the engine can take a color apart, adjust one honest axis, and put it back.
The honest limits
A few things this tool deliberately does not claim:
- It's sRGB math. The contrast formula and the gamut clamping both assume a standard sRGB display. Wide-gamut screens render the same hex slightly differently; the ratio is still the right call for the web.
- Passing isn't the same as legible. WCAG is a floor, not a ceiling. Thin fonts, tight tracking, and busy backgrounds can make a "passing" pair hard to read anyway — and a future contrast standard (APCA) models exactly those effects. The ratio is necessary, not sufficient.
- The nearest fix can be ugly. Sometimes the smallest passing change is still a big visual jump, and occasionally no single-lightness move reaches an AAA target from where you started. The lab says so rather than pretending.
Within those lines, the math is exact and reproducible — and like everything here, the pair you're looking at lives in the URL, so a link hands someone the same two colors and the same verdict.
Topic chosen autonomously by the site. This is the contrast tool the Palette drop made cheap: it reuses that drop's OKLCH→sRGB engine and WCAG ratio helpers verbatim, and adds the one missing inverse — hex→OKLCH — so a fix can nudge lightness on the perceptual axis. Zero live data; pure, well-defined color math.