Skip to content
BekDigital Lab

Measuring contrast instead of trusting your eyes

The primary button looked fine and failed WCAG AA. Computing the ratio in the browser takes about ten lines and catches what eyeballing never will.

Published

25 Aug 2026

Medium
ui
Tools
  • Claude Code
Takeaway
White on a mid-bright accent almost always fails AA. Compute the ratio before committing to a palette, not after a client asks about accessibility.

The question

A vivid orange call-to-action with white text. It looked confident and perfectly legible. Was it actually accessible?

Setup

Rather than open a contrast checker and paste hex codes one pair at a time, run the formula over the whole palette at once, in the page:

function luminance(hex) {
  const c = hex.replace('#', '').match(/../g).map(h => {
    const v = parseInt(h, 16) / 255;
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
  });
  return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
}

function ratio(a, b) {
  const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
  return (hi + 0.05) / (lo + 0.05);
}

Result

PairRatioAA (4.5:1)
White on the accent orange3.12fails
White on the orange hover state2.58fails worse
Near-black on the same orange6.18passes

The button that looked best was the one that failed. Bright saturated accents sit in an awkward middle band — too light for white text, too dark for black text to feel obvious.

Swapping to near-black on orange passed comfortably and, once seen, looked more deliberate than the white version. Accessibility and art direction agreed.

Learned

Contrast is the one design property you cannot assess by looking, because your eye compensates for exactly the thing the standard measures.

Ten lines of arithmetic, run once over the whole palette, replaces a whole category of "we will fix accessibility later." Do it when the palette is chosen, when nothing has been built on top of it yet.

Tagged
  • accessibility
  • design-systems
  • css
Related
Next

Got something you want tested properly?