Frontend · CSS

Modern CSS Color Functions — A Field Guide

CSS color has quietly leapt forward. oklch, color-mix(), and relative color syntax solve real problems that hex and hsl never could — especially for building consistent design systems.

John Kihiu12 min read

For years CSS color meant hex codes and, if you were organised, hsl. Modern CSS added color functions that are not just new syntax but genuinely better tools — perceptually uniform color spaces, blending, and deriving colors from other colors. For anyone building a design system, these solve problems the old formats made unnecessarily hard, and they are well-supported enough to use now.

oklch: perceptually uniform color

The standout is oklch() (and its cousin oklab), a perceptually uniform color space. Its three values — lightness, chroma, hue — behave the way your eyes expect: change the lightness and the perceived brightness changes proportionally, unlike hsl where the same lightness value looks wildly different across hues. This matters enormously for design systems, because you can generate a consistent set of shades, or a palette across hues at matching brightness, and have them actually look consistent.

CSS · a perceptually consistent scale with oklch
--brand-h: 152;
--brand-c: 0.09;
--brand-500: oklch(0.62 var(--brand-c) var(--brand-h));
--brand-400: oklch(0.70 var(--brand-c) var(--brand-h)); /* lighter, same feel */
--brand-600: oklch(0.54 var(--brand-c) var(--brand-h)); /* darker,  same feel */

color-mix() for blending

color-mix() blends two colors in a chosen color space directly in CSS — no preprocessor, no manual calculation. This is how you create tints and shades, hover states, and translucent variants from a base color without hardcoding each one. Mixing a brand color with white or black gives you a scale; mixing with transparent gives you alpha variants. It turns color relationships into something the browser computes from your source colors.

Relative color syntax

Relative color syntax lets you derive a new color from an existing one by taking it apart and modifying channels — take this color and increase its lightness, or reduce its chroma. Combined with oklch, this is powerful for design systems: define one brand color and derive the entire family from it in CSS, so changing the source color updates everything downstream. The relationships live in the code rather than in a pile of disconnected hex values.

These replace the preprocessor color toolkit

Sass and Less became popular partly for color functions — darken, lighten, mix. Modern CSS now does all of that natively, and better, because oklch makes the results perceptually consistent in a way the old preprocessor functions were not. For color, you increasingly do not need a preprocessor at all; the platform does it, live, in the browser.

Modern CSS color — oklch for perceptually uniform palettes, color-mix() for blending, and relative color syntax for deriving colors from a source — replaces the old hex-and-preprocessor approach with tools that produce genuinely consistent results. For design systems especially, defining a palette in oklch and deriving its variations natively means your colors look as coherent as they are meant to, with the relationships expressed in code the browser understands.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.