Articles /
color-mix(): blending colors in CSS
Generate hover shades, semi-transparent overlays, and entire palettes from a single base color — no preprocessor needed.
Basic syntax
color-mix() takes a color space and two colors with optional percentages. The result is a new color blended in that space.
/* mix 50/50 in oklch */
background: color-mix(in oklch, oklch(65% 0.22 270), oklch(80% 0.15 145));
/* mix 70% of the first color, 30% of the second */
background: color-mix(in oklch, oklch(65% 0.22 270) 70%, oklch(80% 0.15 145));
Choosing a color space
The color space matters. Mixing in srgb can produce muddy mid-tones; oklch preserves perceptual lightness and chroma.
/* srgb — familiar but can desaturate */
color-mix(in srgb, red, blue)
/* oklch — perceptually uniform, best for UI work */
color-mix(in oklch, oklch(60% 0.25 30), oklch(60% 0.25 270))
/* hsl — hue interpolation is intuitive but lightness is uneven */
color-mix(in hsl, hsl(0 80% 50%), hsl(240 80% 50%))
in oklch is almost always the right choice. It avoids the grey-zone artifacts common in srgb mixing.Hover and active states
The most practical use case: derive darker and lighter variants from a single base color.
:root {
--brand: oklch(62% 0.24 275);
}
.btn {
background: var(--brand);
}
.btn:hover {
/* 20% darker by mixing with black */
background: color-mix(in oklch, var(--brand) 80%, black);
}
.btn:active {
background: color-mix(in oklch, var(--brand) 65%, black);
}
Alpha blending with transparent
Mix any color with transparent to get a semi-transparent version. This is cleaner than manually slicing the alpha channel.
.overlay {
/* 40% opacity version of brand */
background: color-mix(in oklch, var(--brand) 40%, transparent);
}
.border-subtle {
border: 1px solid color-mix(in oklch, var(--text) 15%, transparent);
}
Design token scales
Build an entire shade scale from one base color using color-mix() and custom properties.
:root {
--blue: oklch(58% 0.22 265);
--blue-100: color-mix(in oklch, var(--blue) 15%, white);
--blue-200: color-mix(in oklch, var(--blue) 30%, white);
--blue-300: color-mix(in oklch, var(--blue) 50%, white);
--blue-500: var(--blue);
--blue-700: color-mix(in oklch, var(--blue) 70%, black);
--blue-900: color-mix(in oklch, var(--blue) 40%, black);
}
--blue and every shade updates automatically. This is the single-source-of-truth approach that design systems need.Browser support
color-mix() is supported in all major browsers since mid-2023. For older browsers, provide a fallback color before the color-mix() declaration.
- Always declare a plain color fallback on the line before.
- Pair with
@supports (color: color-mix(in oklch, red, blue))for complex fallback logic. - Combine with
@propertyto animate mixed colors via typed custom properties.