Contrastproof

Find and fix every color contrast failure on your website.

Contrastproof renders your page in a real browser, measures every color pair against WCAG, and gives you the exact color to use instead, with your hue held.

Free, no account, usually under 30 seconds.

contrastproof.com/s/substack.com

substack.com

Scanned 2026-08-27 · https://substack.com/

9 failing pairs
Failing pairs
9
Elements affected
255
Needing eyes
24
Dark mode
audited
01/30 elements13px · 400 · needs 4.5:1

On your site now

on2.91:1

Corrected

on4.51:1

Hue held exactly. Chroma reduced by 0.025 to stay inside sRGB. Perceptual shift 0.115.

02/17 elements15px · 400 · needs 4.5:1

On your site now

on2.91:1

Corrected

on4.51:1

Hue held exactly. Chroma untouched, only lightness moved. Perceptual shift 0.689.

3 more below, plus the dark-mode pass and the palette

A real scan of substack.com, run by the same engine your website goes through. Nothing here is illustration: this is the report, exactly as it arrives.

Nobody catches these by looking.

92 elements on substack.com sit at 4.48:1 against a requirement of 4.5. They miss by 0.02. No eye finds that, and no free checker tells you the gray that fixes it is #777677.

01/92 elements15px · 400 · needs 4.5:1

On your site now

on4.48:1

Corrected

on4.52:1

Hue held exactly. Chroma untouched, only lightness moved. Perceptual shift 0.003. Not visible side by side.

02/1 element13px · 400 · needs 4.5:1

On your site now

on1.02:1

Corrected

on4.50:1

Hue held exactly. Chroma untouched, only lightness moved. Perceptual shift 0.383.

03/5 elements15px · 400 · needs 4.5:1

On your site now

on4.03:1

Corrected

on4.55:1

Hue held exactly. Chroma reduced by 0.007 to stay inside sRGB. Perceptual shift 0.030. Not visible side by side.

Every color that painted on the page

Ordered by how much of the page each covers, measured against the dominant surface. Surfaces are not held to a text ratio, so they are not marked against one.

  • #7777771.00
  • #777777surface
  • #ffffffsurface
  • #3637372.67
  • #eeeeeesurface
  • #ffffff4.48
  • #ff67191.54
  • #ff6719surface
  • #232525surface
  • #0000004.69
  • #c8c8c8surface
  • #000000surface

Three things a color picker cannot do.

1Render

The color that matters is the one that composited on screen, after the cascade, after JavaScript, after the semi-transparent panel. We load your page in Chromium and scroll it so lazy sections paint before we measure.

2Group

145 failing elements on this scan are really 5 color pairs. You do not fix elements one at a time, you fix a pair once and it lands everywhere. That is the difference between a task and a list.

3Repair

We move lightness in OKLCh, hold your hue exactly, and give up chroma only when the sRGB gamut forces it. It is arithmetic, not a language model, so it is instant and it is the same answer every time.

Scanning is free. Paying is a separate decision, later.

There is no plan to choose and nothing to sign up for. You scan, you read what came back, and only then is there anything to buy.

  1. 1Scan
    Free

    Type your address. We render the page, scroll it, and measure every color pair against WCAG, in light and in dark. No account, no card, as often as you like.

  2. 2Read
    Free

    Your score, how many pairs fail and how many elements they affect, and your 3 worst pairs in full, each with the exact color that fixes it. Shareable link.

  3. 3Unlock
    $20 once

    Only if you want the rest: every remaining pair, the dark-mode pass, the elements behind each finding, and a CSS file you can paste in. One payment, that one site, no subscription.

Free, no account, usually under 30 seconds.

This button never charges you. Payment only appears on your own report, after you have seen what we found.

This page is the output of the thing it sells.

Every color on Contrastproof was produced by the same repair function you just watched work, and a test fails our build if any pair here drops below AA in either theme. That test has already caught us twice: our secondary gray started at 3.90:1, and our violet button had a 2.61:1 edge on dark cards, which is a button with no visible boundary. Both are fixed above.

Read the method