CSS contrast-color() for Readable Text

Readable text without manual contrast checks

Picking readable text used to mean hardcoding color: white or color: black for each background. contrast-color() does the math automatically, returning whichever meets WCAG AA contrast against the given color.

Old way10 lines
/* Hardcode a text color per background */.badge-blue   {  background: #1e40af;  color: white;}.badge-yellow   {  background: #fde047;  color: black;}/* Repeat for every color variant */
Modern
4 lines
.badge   {  background: var(--bg);  color: contrast-color(var(--bg));}
Newly availableSince 202680% global usage

Since 2026 this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

Works in all modern browsers. May need a fallback for older browsers.

147+
146+
26+
147+
contrast-color() picks white or black automatically
Badge
Badge
Badge
Badge
Badge
Badge
Badge
Badge
color: contrast-color(var(--cc-bg))

Zero guesswork

The browser calculates contrast automatically. No WCAG math, no hardcoded overrides for each background.

Themeable by default

Change --bg to any color and the text color adjusts. Works with dynamic colors and user preferences.

Accessible by design

contrast-color() targets WCAG AA contrast. Readable text is the default, not an afterthought.

Old Approach
Manual
Hardcoded per background
Modern Approach
contrast-color()
Automatic, accessible
Lines Saved
10 → 4
Per color variant

How it works

contrast-color(bg) takes a background color and returns either black or white, whichever meets WCAG AA contrast requirements against that background. No JavaScript, no preprocessor, no lookup table.

The old approach meant manually choosing color: white or color: black for each background, and repeating that decision every time a new color was added. With user-generated colors or dynamic themes, this quickly becomes unmanageable in plain CSS.

Combine it with custom properties for maximum flexibility: color: contrast-color(var(--bg)) means you only define --bg and the browser handles the rest. It became Baseline Newly available in 2026 (Chrome 147, Firefox 146, Safari 26, Edge 147).

ESC