Dev.to WebDev 🛠 Dev 👁 1 📖 2 min read

Your color palette probably fails accessibility. Here's how to check it in 30 seconds

Here's an uncomfortable stat: most color palettes that look great fail the most basic accessibility test — text contrast. I learned this the hard way. I built a landing page with a palette I loved: soft coral text on a

Here's an uncomfortable stat: most color palettes that look great fail the most basic accessibility test — text contrast.

I learned this the hard way. I built a landing page with a palette I loved: soft coral text on a warm cream background. Beautiful in a screenshot. Then someone told me they literally couldn't read my hero heading on their phone in daylight.

The palette wasn't the problem. The pairing was.

The 30-second check

Text readability is measured by contrast ratio — how different your text color is from the background behind it. The WCAG standard is simple:

  • 4.5:1 minimum for normal body text (AA)
  • 7:1 for the stricter AAA level
  • 3:1 for large text (24px+)

Black on white is 21:1 — maximum contrast. My coral-on-cream disaster? About 2.1:1. Nobody with less-than-perfect vision (or a sunny day) had a chance.

The fastest way to check: any contrast checker tool, or the one built into Chrome DevTools — inspect a text element, click the color swatch in Styles, and the contrast ratio is right there with AA/AAA badges.

The formula, if you're curious

The math behind it is relative luminance:

function luminance(r, g, b) {
  const a = [r, g, b].map(v => {
    v /= 255;
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
  });
  return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
}

function contrast(rgb1, rgb2) {
  const l1 = luminance(...rgb1);
  const l2 = luminance(...rgb2);
  return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
}

contrast([255, 255, 255], [17, 17, 17]); // ≈ 18.88

That's the exact formula Chrome, Lighthouse, and every checker uses. No magic.

The workflow fix

The real lesson wasn't "run a checker at the end" — it was choosing pairings up front. Now when I pick a palette, I decide immediately: which color is text, which is background, which are decoration-only. The vivid middle tones that fail contrast? They become borders, accents, and illustrations — never words.

A pattern that always works:

:root {
  --bg: /* your lightest color */;
  --text: /* your darkest color */;
  --accent: /* the vivid one — buttons, badges, never body text */;
}

If your lightest-on-darkest doesn't hit 4.5:1, the palette needs a darker dark or a lighter light. Adjust lightness, not hue — the palette keeps its character.

I ended up building this check into PaletteCSS, a free palette tool I work on — every palette page shows a WCAG contrast table for all color pairings, so you can see which combos are safe for text before you commit. No signup, if you want to sanity-check your current palette.

TL;DR

  1. Body text needs 4.5:1 contrast minimum
  2. Check in DevTools — it's built in
  3. Assign roles when you pick colors: text, background, accent
  4. Vivid mid-tones are for decoration, not words

Your design isn't done when it looks good. It's done when everyone can read it.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.