CSS color recipe
contrast-color() Labels that pick black or white for themselves
contrast-color(var(--bg)) resolves to white or black, whichever contrasts more with the background. One rule then labels a tag of any color, with fallbacks worked out ahead of time for browsers without it.
- Baseline
- Newly available
- First versions
- Chrome 147 · Firefox 146 · Safari 26
- Tested
- 3 of 3 engines
Live example
The recipe, running
Left: the CSS below, as your browser runs it. Right: the same CSS as a browser without the feature reads it, so you see exactly what the fallback gives.
Turn on JavaScript to see whether your browser supports it; the examples work either way.Your browser supports it, so the left example runs the modern path.Your browser does not support it yet, so both examples show the fallback.
The CSS
Copy it as it is
This is the exact CSS the example runs. Fallbacks come first; the modern values follow, so each browser keeps the last line it understands.
contrast-color.css
/* Fallback: the label color worked out ahead of time, per background. */
.tag { padding: 6px 14px; border-radius: 999px; background: var(--bg); color: var(--fallback-ink); }
@supports (color: contrast-color(red)) {
.tag { color: contrast-color(var(--bg)); }
}
How it works
What each part does
The browser decides. The CSS Color 5 draft leaves the contrast algorithm to the browser and warns against relying on WCAG 2 alone. The table below shows what each engine chose for these backgrounds.
Only black or white. It will not find a brand-colored label that passes; for that, choose the color yourself.
The fallback per tag. Each tag carries
--fallback-ink, the one of black and white with more WCAG 2 contrast on its background.
Browser support
Where it runs
First version of each browser with the feature, from the web-features project and MDN’s browser-compat-data. “No” means not supported yet.
- contrast-color()Newly availableBaseline newly available since 10 April 2026: every core browser has it, but older versions in use may not.
| Browser | contrast-color() |
|---|---|
| Chrome | 147 |
| Chrome for Android | 147 |
| Edge | 147 |
| Firefox | 146 |
| Firefox for Android | 146 |
| Safari | 26 |
| Safari on iOS | 26 |
Support reviewed on against web-features 98723fd and browser-compat-data 3b28abe.
Tested
Tested in three engines
| Engine | Version | Supported | As written | Fallback |
|---|---|---|---|---|
| Chromium | 147.0.7727.15 | Yes | Pass | Pass |
| Firefox | 148.0.2 | Yes | Pass | Pass |
| WebKit | 26.4 | Yes | Pass | Pass |
What each engine chose
| Background | Black text | White text | Fallback | Chromium | Firefox | WebKit |
|---|---|---|---|---|---|---|
#3B82F6 | 5.71:1 | 3.68:1 | Black | Black | Black | Black |
#EF4444 | 5.58:1 | 3.76:1 | Black | Black | Black | Black |
#22C55E | 9.22:1 | 2.28:1 | Black | Black | Black | Black |
#F59E0B | 9.78:1 | 2.15:1 | Black | Black | Black | Black |
#8B5CF6 | 4.96:1 | 4.23:1 | Black | Black | Black | Black |
#0F172A | 1.18:1 | 17.85:1 | White | White | White | White |
All three engines chose the same label color for every background, and it matched the fallback.
Run on in Chromium 147.0.7727.15, Firefox 148.0.2 and WebKit 26.4, with Playwright.
Accessibility
Measured, not assumed
Whichever of black and white has more WCAG 2 contrast never falls below 4.58:1 on any background, so that choice always clears AA for body text but never guarantees AAA.
References
Go to the source
- CSS Color Module Level 5: contrast-color()www.w3.org
- Understanding WCAG 2.2: Contrast (Minimum)www.w3.org
- web-features at 98723fdgithub.com
- MDN browser-compat-data at 3b28abegithub.com