color-mix() and modern color
Derive a whole palette from one brand colour.
Stop hand-picking tints and shades in a colour picker β color-mix() blends two colours in a chosen colour space, so one token can generate its own hovers, surfaces, and overlays.
Blend two colours in a named space
color-mix() takes an interpolation colour space and two colours, each with an optional percentage: color-mix(in srgb, red 30%, blue). The space comes first because where you interpolate changes the result β the same two endpoints mixed in srgb versus in oklch trace different paths and produce different midpoints.
The percentages set how much of each colour you want. Give one side a percent and the other is inferred (red 30% pairs with blue at the remaining 70%). Give both and they're normalised to sum to 100%. This is real CSS maths at compute time, not a preprocessor β the inputs can be var() tokens or even currentColor, so the blend stays live as the cascade changes.
Tints, shades, and tones from one token
The classic use is generating a scale from a single brand colour. Mix toward white for a tint (lighter), toward black for a shade (darker), and toward gray for a tone (less saturated). color-mix(in oklab, var(--brand) 85%, black) is "brand, nudged 15% darker" β exactly what a hover state usually wants, without committing a second hex value to your stylesheet.
Mixing toward transparent is a fourth trick: color-mix(in srgb, var(--brand) 12%, transparent) is a faint, brand-tinted wash you can drop behind text. It reads more naturally than guessing at an rgba() alpha because you think in "12% of the brand", not in opacity.
Pick the right space, and know oklch
For perceptual evenness prefer oklab / oklch β Oklab is a uniform space, so a 15% mix toward black looks like a 15% step, where the same step in srgb can lurch or wash out (especially through saturated blues and reds). oklch is the polar form (lightness, chroma, hue); mixing in it interpolates hue along the shorter arc, which keeps blends vivid instead of dragging them through muddy grey. Reach for in srgb mainly when you specifically want the legacy, gamma-encoded blend.
A close cousin is relative colour syntax β oklch(from var(--brand) calc(l * 0.85) c h) derives a new colour by pulling apart an existing one's channels (l, c, h) and recombining them. color-mix() blends two colours; relative colour transforms one. Both let a design system carry a single source colour and compute the rest.
Try it 4 examples
Tints: mix the brand toward white
HTML+CSS+JSintroThe four swatches render as one row going from the full amber --brand to progressively paler tints, each step holding less brand and more white. It shows a whole lightness ramp built from a single token β no second colour was hard-coded.