Live, interactive demos of modern CSS color features — built from
JD Steinbach’s slides.
Everything here is plain CSS: no Sass, no JS color math. Toggle the theme above to watch
light-dark() and color-scheme do their thing. Best viewed in a recent
Chrome, Safari, or Firefox.
Theming light-dark() · color-scheme
One declaration holds both a light and a dark value. The browser picks based on the active
color-scheme — driven by the system preference or the toggle in the header.
Every surface, border, and text color on this page is built this way.
--text: light-dark(oklch(22% 0.02 264), oklch(94% 0.01 264));
--bg: light-dark(oklch(98% 0.01 264), oklch(18% 0.02 264));
No media query, no extra class — the value resolves automatically per scheme.
Perceptual color oklch()
OKLCH separates lightness, chroma (colorfulness), and hue in a way that matches human perception. Equal lightness looks equally light across hues — unlike HSL.
Scales for free relative color syntax
Derive tints and shades from a single base color. oklch(from …) destructures
the base into l c h channels you can do math on — generating a whole scale without a
preprocessor.
Each step is oklch(from var(--base) <lightness> c h) — only the
lightness changes, so hue and saturation stay consistent across the ramp.
Blending color-mix()
Mix two colors by a percentage, in any color space. Interpolating in oklch avoids the
muddy grays you get mixing through srgb.
Readable text contrast-color()
Let the browser choose black or white text for whatever background you throw at it. Drag the hue and lightness — the label stays legible automatically.
Newest feature here — needs a very recent browser. If the text doesn’t flip,
your browser hasn’t shipped contrast-color() yet.
Gradients across color spaces linear-gradient(in …)
The same two endpoints, interpolated through different color spaces. Watch how
oklch sweeps cleanly through vivid hues while srgb dips through gray.