Besides about 150 names (tomato), transparent, currentColor and hex codes (#0f0, #00ff0080), CSS offers color functions. Modern syntax separates channels with spaces and puts alpha after a slash, rgb(21 101 192 / 50%); the comma form and rgba()/hsla() remain valid aliases.
| Notation | Baseline |
|---|---|
| hex, names, rgb(), hsl(), hwb() | Widely available |
| lab() lch() oklab() oklch() color() color-mix() | Widely available (2023) |
| relative colors, light-dark() | Newly available (2024) |
| contrast-color() (black or white for a background) | Newly available (2026) |
rgb(), hsl() and hwb() (hue, whiteness, blackness) describe the sRGB cube, whose numbers do not match perception: at 50% HSL lightness, lime looks far brighter than violet. lab()/lch() (CIE, 1976) and their 2020 refinement oklab()/oklch() are perceptual. oklch(L C H) takes lightness (0-1), chroma (0 upward; 100% = 0.4) and hue, and can reach vivid Display P3 colors that rgb() cannot, which makes it the best space for design tokens.
color-mix(in oklch, a, b 25%) blends in the named space. Relative color syntax, oklch(from var(--x) l c h), exposes a color's channels (l, c, h or r, g, b, alpha) for rewriting with calc(). light-dark(a, b) picks by the element's declared color-scheme (Dark Mode).
<style>
p { display: flex; gap: 3px; margin: 4px; align-items: center; font: bold 12px sans-serif; }
b { width: 124px; flex: none; }
i { flex: 1; height: 34px; display: grid; place-items: end center; background: var(--c);
font: 10px sans-serif; color: #fff; text-shadow: 0 0 2px #000; }
.ld { --c: light-dark(#e3f2fd, #0d2a4a); color: light-dark(#0d47a1, #bbdefb);
text-shadow: none; }
</style>
<p><b>One blue</b>
<i style="--c: #1565c0">hex</i><i style="--c: rgb(21 101 192)">rgb</i>
<i style="--c: hsl(212 80% 42%)">hsl</i><i style="--c: hwb(212 8% 25%)">hwb</i>
<i style="--c: lab(42.3 4.3 -55.2)">lab</i><i style="--c: lch(42.3 55.3 274.5)">lch</i>
<i style="--c: oklab(0.51 -0.04 -0.16)">oklab</i><i style="--c: oklch(0.51 0.16 256)">oklch</i>
</p>
<p id="hsl"><b>hsl(h 90% 50%)</b></p>
<p id="okl"><b>oklch(0.7 0.13 h)</b></p>
<p><b>Derived</b>
<i style="--c: color-mix(in oklch, #1565c0, #ef6c00)">mix oklch</i>
<i style="--c: color-mix(in srgb, #1565c0, #ef6c00)">mix srgb</i>
<i style="--c: oklch(from #1565c0 calc(l + 0.2) c h)">l + 0.2</i>
<i style="--c: oklch(from #1565c0 l c calc(h + 180))">h + 180</i></p>
<p><b>light-dark()</b><i class="ld" style="color-scheme: light">light</i>
<i class="ld" style="color-scheme: dark">dark</i></p>
<script>
for (const h of [30, 90, 150, 210, 270, 330]) {
hsl.innerHTML += `<i style="--c: hsl(${h} 90% 50%)"></i>`;
okl.innerHTML += `<i style="--c: oklch(0.7 0.13 ${h})"></i>`; }
</script>
The HSL row jumps from glaring lime to deep violet while the OKLCH row stays even, and the sRGB mix of blue and orange turns muddy where the OKLCH mix stays saturated.