css

contrast-color(): readable text from one color

It's both annoying and awesome when you find a CSS attribute that just solves a problem you've spend collective hours trying to solve yourself. contrast-color() is one of those attributes.

Theme pickers, status badges, generated avatars, user labels... the background color can come from anywhere, and can change dynamically. The foreground usually turns into a second token you have to remember to keep in sync.

contrast-color() makes that pairing much simpler. Give it one color and it resolves to either black or white, whichever has stronger contrast against that solid background.

MDN has contrast-color() as Baseline 2026. The Web Platform Features Explorer lists it as Baseline since April 10, 2026, after Chrome 147 completed support across the core browser set, so it's widly available.

The important caveat: this is not a palette generator. The current CSS Color Level 5 version returns only black or white. It is great for small UI surfaces where the background is a solid dynamic color. It is not a replacement for checking real brand palettes, gradients, images, disabled states, or those awkward mid-tone colors that technically pass a formula but still feel shitty to read.

Use a fallback first, then let supporting browsers take over:

.chip {
	background: var(--chip-color);
	color: white;
	color: contrast-color(var(--chip-color));
}

Unsupported browsers keep the fallback. Supported browsers stop making you maintain pairs like --project-green-bg and --project-green-fg for every little chip.

One color in. Black or white out.

Violet

Readable text from one background token.

Change the color and the foreground follows without JavaScript or paired theme variables.

color: contrast-color(var(--sample));

Preset surfaces

Each button uses its own background as the input to contrast-color().

Status tokens

Badges stay readable when the tone changes at runtime.

Readyshipping
Reviewqueued
Blockedneeds input
Nightlydeploying