Field Notes

One brand color cannot serve a light and a dark surface

A link blue used on a navy header and on a pale panel fails on one of them. Moving it to fix the header breaks the panel. The only fix that passes both is two tokens, one per surface. Here are the numbers, and why no single value works.

Published

  • color
  • contrast
  • design tokens
  • dark mode

A site has a brand blue. It is the link color. It appears on the navy header, where the text has to be lighter than the background, and in a pale sidebar panel, where the text has to be darker. One token, two jobs. The jobs pull in opposite directions, and the token can only move one way.

The numbers

Here is the blue, and what happens when it is moved to fix the header.

Text color On black On the pale panel Passes
The shared blue, as shipped 3.87:1 5.01:1 Panel only
The shared blue, moved to fix the header 4.42:1 4.38:1 Neither
A private blue for the dark side 4.97:1 3.90:1 Dark side
The original blue, kept for the panel 3.87:1 5.01:1 Panel

The second row is the trap. A tool that treats the token as one value and nudges it toward passing will find a point where both ratios are close to 4.5 and neither reaches it. In the source work for this note the tool settled at 4.40:1 on both sides, a tenth short in each direction, and ten elements stayed failing. The ratios in the table are the plain contrast formula on the hex values the lab ships.

The last two rows are the fix. Two tokens, each with one job. The dark-side blue is lighter; the panel blue is the original. Both pass where they are used, and neither is asked to work anywhere else.

Why no single value works

Contrast depends on how far apart two luminances are. On the dark header, the text passes by being bright. On the pale panel, it passes by being dim. A color cannot get brighter and dimmer at once. Every move toward one side is a move away from the other. There is a narrow band in the middle, around 4.4:1 on both, and it is a band of failure.

The Contrast Circuit draws this as a map. Contrast is a point with text luminance across and background luminance up. The passing region is two wedges, one where the text is much lighter and one where it is much darker, with a line between them where the two luminances match. A shared color on two backgrounds is two points, one in each wedge's neighbourhood, and the move that helps one point drags the other toward the line.

What to do with tokens

  • Give each surface its own token. --link on light, --link-on-dark on dark. Set both. Do not derive one from the other.
  • Group by surface, not by name. When you audit, list every background a token appears on. A token with two backgrounds is two pairs to check.
  • Let the dark theme have its own palette. The Color Lab export writes one block per surface for this reason. A dark palette is not the light palette inverted.
  • When a tool reports it "split" a token, check that it split it into two values. A split that produces one new shared value has not split anything.

An agent rule

That is rule AW-COLOR-004 in the ruleset. It asks an agent to group elements by token, list the backgrounds each token appears on, and report any token that passes on one and fails on another. Corpus page 38 plants exactly this blue on a navy header and a pale panel.

Try it

Open the Contrast Circuit and scroll to the last table, "One color, two backgrounds". The preset buttons under the map put the shared blue on black and on the panel, before and after the move. Watch the point move toward the line and never cross it.

Sources

  • w3.org, Understanding Success Criterion 1.4.3: Contrast (Minimum)
  • a11y.world, the Contrast Circuit lab and its shared-color table

Open the companion lab

  • Fix a failing color with the smallest move

    A color fails contrast and you want to change it as little as possible. There are two short paths, lightness alone and a mix toward black or white. They often end at the same place, and when they do not, the difference is hue. Here is how far each one travels, with numbers.

  • Why your focus ring vanishes in dark mode

    A ring designed on a white mockup is a coin toss once the page can be dark. The fix is not a darker ring. It is a second tone.

  • Charts that still read when printed in grey

    A chart passes when it still carries its message on a grayscale printer. That means three lightness levels, not three hues; dash and shape before pattern; and labels on the data instead of a legend. This is the rule every chart on this site follows, written down.

Spotted something this note gets wrong?

Corrections and better examples are the best kind of message.

Send a correction