Saramsha

No. 052  ·  7 November 2026

A Red That Fails, a Grey That Passes

A contrast checker never looks at hue or saturation — it only computes luminance, how much light a colour reflects. That is why pure red (#FF0000) narrowly fails WCAG's test for white text, while a flat, ordinary grey (#767676) passes it. Drag the dial to try every hue, then run the same test on a real photo.

luminance by hue white text clears AA below this line black text clears AA above this line

Now on a real photo

Pull the colours out, run the same test

Every photo is a few dominant colours and a lot of blending. Cluster the pixels down to six, and check each one the same way — against white text and against black.

About this piece

Brightness, measured honestly

Drag any colour picker's lightness slider from black to white and it moves in a straight, even line — 0% is black, 50% is "halfway", 100% is white, by definition, because that is how the HSL colour model was built: it is a geometric description of a colour cube, not a measurement of anything your eye does. Pure red, pure green and pure blue all sit at exactly 50% lightness in HSL, because each one is as far from black as it is from white along its own axis of that cube. But stand them side by side and they plainly do not look equally bright. Green looks lit up; blue looks like it is sitting in shade. HSL lightness never claimed otherwise — it just isn't answering the question "how much light does this reflect," which is the only question a contrast checker actually asks.

The real answer comes from relative luminance, the quantity the WCAG 2.1 accessibility standard defines for exactly this purpose: L = 0.2126R + 0.7152G + 0.0722B, computed after converting each 0–255 channel out of the sRGB gamma curve and into linear light. Those three weights are not arbitrary — they come from how sensitive the human eye's three cone types are, and green dominates the sum because the eye is far more sensitive to green light than to red or blue at the same physical intensity. Run pure red (255,0,0) through that formula and you get a luminance of about 0.213. Run the grey #767676 — R=G=B=118 — through it and you get almost the same number, about 0.183, even though the two colours look nothing alike and HSL would call red "brighter" (50% lightness) than that grey (46%).

The exact numbers behind the headline

WCAG's contrast ratio between two colours is (L1 + 0.05) / (L2 + 0.05), using the lighter luminance as L1. White text (L = 1.0) over pure red (L ≈ 0.213) comes out to (1.0 + 0.05) / (0.213 + 0.05) ≈ 4.00 — just short of the 4.5 the "AA" level requires for ordinary body text. White text over #767676 (L ≈ 0.183) comes out to (1.05) / (0.233) ≈ 4.54 — just over the line. Neither of those is a close call you'd catch by eye; the whole point of the formula is to catch exactly this kind of near-miss that eyeballing a colour cannot.

What the chart's shaded band means

For any fixed saturation and lightness, sweeping the hue from 0° to 360° traces out how luminance actually changes — and it is not a smooth, even wave the way HSL's circular hue wheel might suggest. At full saturation and 50% lightness, luminance peaks near yellow (hue ≈ 60°, where red and green both run at full strength) and bottoms out near blue (hue ≈ 240°, the dimmest of the three channels on its own). The two dashed lines mark the luminance above which black text clears AA (4.5:1) and below which white text clears it; the shaded band between them is a trap — colours in that middle range of luminance are too light for black text to read reliably and too dark for white text either, and only a darker or lighter version of the same hue escapes it.

How the photo palette works, and what it skips

The photo tool runs a small k-means clustering over the image's pixels (sampled, not every one, for speed) to find six representative colours, then puts each one through the identical luminance and contrast formula. It skips a few things a professional tool would handle: it does not account for anti-aliased text, font weight, or the "large text" exception WCAG grants for text at 24px bold or larger (AA only needs 3:1 there, AAA needs 4.5:1, instead of 4.5:1 and 7:1 for body text) — and it treats every pixel equally rather than weighting by where text is likely to sit. Treat it as a fast first pass, not a substitute for checking the real rendered page.

Sources: WCAG 2.1, Success Criterion 1.4.3 (Contrast Minimum) and 1.4.6 (Contrast Enhanced), and the relative luminance definition in the same specification's appendix. #767676 is the grey commonly cited as sitting almost exactly on the 4.5:1 line against white — this page computes it live rather than taking that on faith.