Quick Answer

The CSS color-mix() function blends two colors in a chosen color space. Syntax: color-mix(in oklch, red 50%, blue). The color space matters — oklch is perceptually uniform and avoids the muddy mid-tones that srgb and hsl produce. Use this playground to compare all five supported spaces side-by-side and copy the result.

Color Mix Playground

Updated

The CSS color-mix() function, now supported in all modern browsers, lets you mix two colors directly in stylesheets — no preprocessor required. But the choice of color space dramatically affects the result: mixing red and green in sRGB gives a muddy brown, while oklch produces a vibrant yellow. This playground lets you compare all five supported color spaces side by side, so you can pick the right one for your design system.

color-mix() is the feature that finally makes CSS-native design tokens viable. For years, "design tokens" in CSS meant a hex value and a Sass darken() function that didn't really exist at runtime. Now you can derive a tint scale, a hover state, or a disabled state from a single base color, in pure CSS, without a preprocessor. The oklch.com playground from Andrey Sitnik is the fastest way to develop intuition for the OKLCH color space; the MDN reference for color-mix() covers the syntax exhaustively; and the underlying machinery is specified in CSS Color Module Level 5. The honest caveat: OKLCH's lightness/chroma/hue model is genuinely harder to reason about than HSL on day one. Spend an afternoon with the picker and it clicks; skip that step and you'll write OKLCH that looks the same as the HSL you replaced.

Color 1
Mixed
Color 2

What is color-mix()?

The CSS color-mix() function takes two colors and a mixing ratio, and returns the result of blending them in a specified color space. The syntax is color-mix(in <color-space>, <color1> <percentage>, <color2>), where the percentage indicates how much of the first color to include. A 50% mix produces an equal blend of both colors, while 25% would give you mostly the second color with just a quarter of the first.

The choice of color space matters significantly. sRGB performs a simple channel-by-channel average, which can produce muddy or desaturated results when mixing colors that are far apart on the color wheel. Perceptually uniform spaces like oklch and lab produce results that look more natural to the human eye, because they are designed so that equal numeric changes correspond to equal visual changes. For example, mixing red and cyan in sRGB produces a dull gray, while oklch produces a more vibrant intermediate color.

Before color-mix(), creating color variations in CSS required either hard-coding every shade manually, using a CSS preprocessor like Sass with its mix() function, or computing colors in JavaScript. With native color-mix(), you can derive an entire palette of tints, shades, and tonal variants from a single base color directly in your stylesheet, and those colors update automatically when the base changes. This is transformative for design systems and theming.

How to use this tool

Pick two colors using the color pickers in the controls panel. Adjust the ratio slider to control the blend — 0% means fully color 2, 100% means fully color 1, and 50% is an equal mix. Choose a color space from the dropdown to see how different interpolation spaces affect the mixed result. The three preview boxes show color 1, the computed mixed result, and color 2 side by side for easy comparison.

Once you find a mix you like, copy the Direct CSS output to paste the color-mix() function directly into your stylesheet, or use the CSS Variables format if you prefer to manage your colors as design tokens. The "Copy Share URL" button encodes your current color selections, ratio, and color space into the page URL so you can share a specific blend with collaborators or bookmark it for reference.

Practical examples

Creating tint and shade scales from a base color

One of the most common uses of color-mix() is generating a full tint and shade scale from a single brand color. By mixing with white you create tints (lighter versions), and by mixing with black you create shades (darker versions). Using oklch as the color space keeps the results perceptually even across the scale.

:root {
  --brand: #6366f1;

  /* Tints (lighter) */
  --brand-50:  color-mix(in oklch, var(--brand) 5%, white);
  --brand-100: color-mix(in oklch, var(--brand) 10%, white);
  --brand-200: color-mix(in oklch, var(--brand) 25%, white);
  --brand-300: color-mix(in oklch, var(--brand) 40%, white);
  --brand-400: color-mix(in oklch, var(--brand) 60%, white);

  /* Base */
  --brand-500: var(--brand);

  /* Shades (darker) */
  --brand-600: color-mix(in oklch, var(--brand) 80%, black);
  --brand-700: color-mix(in oklch, var(--brand) 60%, black);
  --brand-800: color-mix(in oklch, var(--brand) 40%, black);
  --brand-900: color-mix(in oklch, var(--brand) 25%, black);
}

Accessible text color contrast using color-mix

When placing text on a colored background, you can use color-mix() to derive a text color that guarantees sufficient contrast. By heavily mixing the background color with either white or black, you produce a text color that is related to the background (maintaining color harmony) while being dark or light enough to read.

.badge {
  --bg: #3b82f6;
  background: var(--bg);
  /* Mix 85% black into the background color for dark, readable text */
  color: color-mix(in oklch, var(--bg) 15%, black);
}

.badge-light {
  --bg: #fef3c7;
  background: var(--bg);
  /* Mix 80% black for readable text on a light background */
  color: color-mix(in oklch, var(--bg) 20%, black);
}

Theme color variants (hover, active, disabled states)

Interactive elements need multiple color states. Instead of manually picking hover, active, and disabled colors, derive them from the base color using color-mix(). This keeps all states harmonious and makes it trivial to update the entire set by changing just the base color.

.btn-primary {
  --btn-bg: #8b5cf6;
  background: var(--btn-bg);
  color: white;
}

.btn-primary:hover {
  /* Slightly darker on hover */
  background: color-mix(in oklch, var(--btn-bg) 85%, black);
}

.btn-primary:active {
  /* Even darker when pressed */
  background: color-mix(in oklch, var(--btn-bg) 70%, black);
}

.btn-primary:disabled {
  /* Desaturate by mixing with gray */
  background: color-mix(in oklch, var(--btn-bg) 40%, #9ca3af);
  cursor: not-allowed;
  opacity: 0.7;
}

Common patterns and best practices

CSS color-mix() opens up new patterns for managing color in design systems. Here are some guidelines to help you get the most out of it.

Browser Support

For projects that need to support older browsers, declare a static fallback on the line before the color-mix() rule. The older browser uses the fallback; modern browsers apply the computed mix.

Common Pitfalls

FAQ

Which color space should I use?

For most UI work, oklch is the best default — it's perceptually uniform, meaning equal numeric changes produce equal visual changes. Use sRGB if you need the widest compatibility or are mixing very similar colors. HSL can produce unexpected results with saturated colors because it interpolates through the hue wheel.

Can I mix more than two colors?

The color-mix() function only accepts two colors at a time. To mix three or more colors, you can nest color-mix() calls — for example, color-mix(in oklch, color-mix(in oklch, red 50%, blue) 50%, green). This works but can be hard to read; consider using CSS custom properties to break it into steps.

What's the difference between color-mix() and opacity?

The CSS opacity property affects the entire element, including all of its children, borders, shadows, and text. It makes everything uniformly transparent, and there is no way to exempt individual parts of the element. color-mix(), by contrast, creates a single new, fully opaque color value that can be applied to any individual CSS property — background, text, border, shadow — independently. Use color-mix() when you want to lighten or desaturate a specific color property without affecting the rest of the element.

How does color-mix() compare to relative color syntax?

These two features solve different problems. color-mix() blends two distinct colors together in a specified color space, producing a midpoint between them. Relative color syntax (e.g., oklch(from var(--color) calc(l * 1.2) c h)) lets you take a single color and modify its individual channels — lightness, chroma, hue — to produce a variation. Use color-mix() when you want to combine two colors; use relative color syntax when you want to tweak one channel of one color, such as making it 20% lighter or shifting its hue by 30 degrees.

Can I use color-mix() in gradients?

Yes, color-mix() works anywhere a CSS color value is accepted, and that includes gradient color stops. You can write linear-gradient(color-mix(in oklch, red 50%, blue), white) and the browser will compute the mixed color, then use it as the first stop of the gradient. This is useful for creating gradient palettes derived from a base color, or for producing gradient stops that maintain perceptual uniformity by mixing in the oklch space before the gradient interpolation occurs.

Related guides

Related tools