CSS Color Playground

The 2026 color toolkit in one place: color-mix(), relative color syntax, light-dark(), contrast-color() and wide-gamut fallbacks — with live previews of every result.

Color A
Color B
Mix — 50% B
Mixing space
#6566f1
color-mix(in oklch)
color-mix(in oklch, #6366f1 50%, #f97316)
#7980ff
Relative: lighter
oklch(from var(--brand) calc(l + 0.08) c h)
#9f7700
Relative: complement
oklch(from var(--brand) l c calc(h + 180))

Mixing space comparison

oklch
oklab
lab
hsl
srgb
modern-color.css
:root {
  --brand: oklch(0.585 0.204 277.1);
  --accent: oklch(0.705 0.187 47.6);

  /* Native mixing — no preprocessor */
  --brand-mixed: color-mix(in oklch, var(--brand) 50%, var(--accent));

  /* Relative color syntax: derive states from one source */
  --brand-hover: oklch(from var(--brand) calc(l + 0.08) c h);
  --brand-quiet: oklch(from var(--brand) l calc(c * 0.35) h);
  --brand-complement: oklch(from var(--brand) l c calc(h + 180));

  /* One declaration, both themes */
  color-scheme: light dark;
  --surface: light-dark(oklch(1 0 0), oklch(0.19 0.01 275));
}

.button {
  background: var(--brand);
  color: white;                                /* fallback */
  color: contrast-color(var(--brand));         /* Baseline 2026 */
}

.button:hover { background: var(--brand-hover); }

/* Wide-gamut accent with an sRGB fallback */
.badge { background: #f97316; }
@supports (color: color(display-p3 1 1 1)) {
  .badge { background: oklch(0.705 0.187 47.6); }
}

Stop shipping a preprocessor for color maths

lighten(), darken() and mix() from SCSS all operated at build time on static values. color-mix() and relative color syntax run in the browser against custom properties, which means a color derived from --brand updates the moment --brand changes — including at runtime, from a theme switcher or a user preference.

Mixing space matters

Mix in oklch or oklab for perceptual blends. Mixing in srgb is what CSS did historically and produces darker, duller midpoints. Change the space below with the same two colors to see the difference immediately.

Progressive enhancement pattern

Always order declarations from most conservative to most modern. A browser that cannot parse contrast-color() keeps the previous color declaration, so nothing breaks — you simply do not get the automatic behaviour.

Frequently asked questions

What does color-mix() do?
color-mix() blends two colors in a color space you choose: color-mix(in oklch, var(--brand) 70%, white). It replaces most SCSS lighten/darken/mix helpers with a native, runtime-aware equivalent that works with CSS variables.
What is relative color syntax?
It lets you derive a color from another inside a color function: oklch(from var(--brand) calc(l + 0.1) c h). Channel keywords l, c and h refer to the source color, so you can build hover states without a preprocessor.
What does light-dark() replace?
light-dark(white, black) resolves according to the element's color-scheme, so a single declaration covers both themes without duplicating a media query or a .dark selector block.
Is contrast-color() usable now?
Yes. contrast-color() reached baseline availability in 2026 and picks a maximally readable foreground for a given background. Ship an explicit fallback declaration first for older engines.

Related tools