Accent colors that fail as text
Brand accent colors usually pass the 3:1 threshold for graphics and fail the 4.5:1 threshold for text. Saturation is what makes an accent feel vivid, and saturation barely changes luminance, which is the only thing contrast measures. The fix is two colors: a bright one for marks, a deeper one for text.
The failure, with our numbers
Benchvale's first palette had a single accent at #23A6B8. It looked
correct. It was used for the logo mark, for links, and for the small interface details
that make a design feel finished.
Then we built a tool that checks every pair in a palette against every other pair, pointed it at our own tokens, and found this:
-
#23A6B8on the primary tile#1E5470: 2.82:1. Under the 3:1 floor that interface graphics need, so the logo mark itself would have failed. -
#23A6B8on the page background#F5F7F9: 2.71:1. Nowhere near the 4.5:1 that normal text needs, so every link on the site was failing.
Neither of those is a subtle miss. Both were invisible until something checked that specific pair, and checking every pair rather than the one you happen to suspect is not a step most workflows run before a color ships.
Why it happens
Contrast ratio is built from relative luminance, which weights the three color channels by how much the eye responds to each: about 21% red, 72% green, 7% blue. Saturation barely enters into it.
That is the whole mechanism. A vivid cyan and a dull gray-blue of the same lightness have nearly the same luminance and therefore nearly the same contrast ratio against anything. Everything that makes an accent feel like an accent, the vividness, the pop, the way it draws the eye, is carried by saturation and hue, and none of it is visible to the measurement.
So the color that looks brightest on your screen is very often not the one that has the
most contrast, and the intuition that bright means legible is simply wrong. Yellow is
the clearest case: #FFFF00 looks aggressively bright and sits at 1.07:1
against white.
Why it survives review
Three reasons, and they compound.
The accent is a small share of the page. Most contrast checking happens on body text, which is nearly always a near-black on a near-white and passes comfortably. Nobody thinks to check the link color, because links are not where accessibility problems are expected to live.
It is checked against the wrong background. An accent gets tested against white, decided, and then used on a tile, a card, a colored section and a dark footer. Those are four different ratios and only one of them was ever looked at.
Designers have good monitors. A calibrated screen at full brightness in a controlled room makes 3:1 look fine. The same color on a five year old laptop angled slightly wrong in a bright office is gone.
The fix is two colors, not one
The instinct is to darken the accent until it passes, and that usually ruins it: by the
time #23A6B8 reaches 4.5:1 on white it is a deep teal that no longer reads
as a bright brand color.
The fix is to stop asking one color to do two jobs. Split it:
-
A bright accent, for marks and graphics. Ours is
#2FBFD0. It measures 3.71:1 against the primary tile, which clears the 3:1 graphics threshold with room to spare, and 8.36:1 on the dark background. It is never used for text, and the token file says so. -
A deeper accent, for text and links. Ours is
#0E6B78, which is 5.76:1 on the page background. It is recognizably the same family, so the brand still reads as one thing, and it can carry a sentence.
Both live in the palette with names that say what they are for. The moment a color is
called accent and another is called accent-deep, the next
person to use one has a decent chance of picking the right one. A single
accent gives them nothing to go on.
The other rule this exposes
Running the same check across the rest of our tokens turned up a second failure of the
same shape. The border color for form inputs was a pale mist gray, #C9D3DB,
which measures 1.41:1 against the page background.
Input borders are interface components, so they need 3:1, and this was less than half of
it. Every word on the page passed and the form was a set of boxes you could not see. The
fix was #5A6B7A at 5.12:1 for anything bounding a control, keeping the pale
gray for decorative dividers, which are genuinely exempt.
Two failures, same cause: a color chosen by eye for how it looks, in a role where a threshold applies and nobody had checked which threshold.
How to check your own
Take every color in your palette, not just the accent, and check it against every other color rather than against white. That is 72 checks for a nine color palette, which is enough work that it rarely gets done by hand, and why we built the palette contrast grid to do all of them at once.
For a single pair, the contrast checker will also show you the nearest shade of the same hue that passes, which answers the "it fails, now what" question directly. And if you want the general rules rather than this one failure, how to read a contrast ratio covers what the number means and what each level requires.
Do it before the color ships rather than after. Ours was caught during the brand build, which cost an afternoon. Catching it after forty pages exist costs considerably more, and catching it in an accessibility audit costs more again.