🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
CSS MASTER CLASS /// VISUAL ENGINEERING /// LAYOUT DESIGN /// ANIMATION LAB /// CSS MASTER CLASS /// VISUAL ENGINEERING ///

color-mix(): Native Color Blending In CSS

Learn color-mix()'s syntax for blending two colors with weighted ratios, how to derive design-token-based color states that automatically stay in sync with a brand color, and why the chosen color space meaningfully changes the blended output.

Total XP: 0|💻 css XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

color-mix()

Native color blending in CSS.


🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Deriving a hover state, a tint, or a shade from a base color used to require Sass's darken()/lighten() or a JavaScript color library. color-mix() brings that capability natively into the browser, with a choice of color space that genuinely affects the result.

1Syntax: Color Space, Colors, And Weights

color-mix() takes a required color space declaration (in srgb, in oklch, in hsl, and others), followed by two colors to blend. Without explicit weights, the mix defaults to 50/50. Adding a percentage after either color sets that color's weight in the blend — the two percentages don't need to add up to 100%, but if only one is specified, the other is inferred as the remainder.

This single function replaces what used to require either precomputing every tint and shade ahead of time in a preprocessor, or writing custom JavaScript color-manipulation logic just to produce a hover or active state at runtime.

.badge {
  background: color-mix(in srgb, #FF0099 70%, white);
}
localhost:3000
✓ Native BlendA 70/30 blend of brand pink and white, computed live by the browser — no preprocessor step required.

2The Real Win: Deriving States From Design Tokens

The most valuable pattern isn't blending two hardcoded colors — it's blending a design token with black or white to derive a hover, active, or disabled state that automatically tracks the token. color-mix(in srgb, var(--color-brand) 85%, black) produces a slightly darkened brand color for a hover state, and critically, if --color-brand changes during a rebrand, this hover state recalculates correctly without anyone touching it.

This directly extends the design-token philosophy from the Scalable CSS lesson: instead of hardcoding a second, separately-maintained hover color, you derive it mathematically from the single source of truth, eliminating an entire category of 'the hover state wasn't updated after the rebrand' bugs.

:root { --color-brand: #FF0099; }
.btn:hover {
  background: color-mix(in srgb, var(--color-brand) 85%, black);
}
localhost:3000
Rebrand --color-brand →
hover state recalculates automatically

3The Color Space Argument Isn't Just A Formality

It's tempting to treat in srgb as boilerplate you always include without thinking about it, but the color space genuinely changes how the two colors are interpolated, not merely how precisely the result is represented. Mixing red and lime green directly in sRGB tends to pass through a dull, desaturated brownish-yellow midpoint. Mixing the same two colors in oklch, a perceptually-uniform color space, produces a smoother, more vivid transition that better matches human color perception.

As a practical default: use oklch when the visual smoothness of a gradient-like blend matters (like generating a tint/shade scale), and srgb when you need the mix to behave predictably alongside other sRGB-authored colors in a legacy palette.

color-mix(in srgb, red, lime); /* can look muddy */
color-mix(in oklch, red, lime); /* smoother, more vivid */
localhost:3000
✓ Deliberate Color Space Choiceoklch is a strong default for generating perceptually smooth tint/shade scales from a single brand color.

4Step-by-Step Breakdown

Blending Colors, Natively. Need a color 20% lighter, or a hover state that's your brand color mixed with black? For years that meant reaching for a Sass function or a JavaScript color-manipulation library. color-mix() does it directly in CSS, live, in the browser, in your choice of color space.

The Basic Syntax: Color Space, Then Colors And Weights. color-mix(in srgb, red, blue) blends two colors 50/50 by default, in the specified color space. Adding a percentage after either color adjusts the mix ratio — color-mix(in srgb, red 70%, blue) weights the result toward red.

color-mix() Syntax. In color-mix(in srgb, red 70%, blue), what does the 70% control?

  • The opacity of the final mixed color
  • How much red contributes to the final blend, relative to blue
  • The lightness value of red specifically

Mixing With Tokens Instead Of Hardcoded Colors. color-mix()'s biggest practical win is that its arguments can be CSS custom properties, letting you derive an entire palette of tints and shades from one brand token at runtime, instead of hardcoding every variant by hand or precomputing them in a preprocessor.

Deriving States From Tokens. What's the benefit of writing a hover state as color-mix(in srgb, var(--color-brand) 85%, black) instead of a separate hardcoded hex value?

  • It renders measurably faster than a hardcoded color
  • If --color-brand changes (e.g. a rebrand), the hover state automatically stays proportionally darker without a separate update
  • There's no practical difference

Choosing A Color Space Changes The Result. The color space named after in genuinely changes the mixed output, not just its precision — mixing in oklch tends to produce perceptually smoother, more even transitions than mixing in srgb, especially for colors far apart on the color wheel, where sRGB mixing can produce a muddy, desaturated middle.

Color Space Choice Matters. Why might color-mix(in oklch, red, lime) look meaningfully different from color-mix(in srgb, red, lime)?

  • Only due to minor floating-point rounding differences
  • Because different color spaces interpolate between colors differently, and oklch is designed to be more perceptually uniform
  • It's inconsistent browser rendering, not a real difference

Native Color Blending Unlocked. You can now blend colors natively in CSS, derive hover and state variants directly from design tokens so they stay in sync automatically, and choose a color space deliberately based on the perceptual quality of the blend you actually want.

Mix Two Colors Together. color-mix() blends two colors in a given color space, without you calculating the result by hand.

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Derived Color-Mix States Must Still Be Manually Verified For Contrast

A hover state computed via color-mix() is only as accessible as its resulting contrast ratio — automatically deriving a color doesn't automatically guarantee it passes WCAG contrast requirements against its background or text.

2oklch-Based Mixing Can Produce More Perceptually Consistent Lightness Steps For Accessible Palettes

Because oklch models perceived lightness more accurately than sRGB, generating a tint/shade scale in oklch tends to produce steps that are more evenly perceptually spaced, which is useful when building an accessible, systematic color scale.

SEO Implications

  • 1

    Deriving Palettes At Runtime Reduces The Number Of Hardcoded Color Declarations Shipped

    Generating tints and shades via color-mix() instead of authoring dozens of precomputed hex values can measurably shrink a design system's CSS footprint.

  • 2

    Eliminating A JavaScript Color Library Reduces Bundle Size And Main-Thread Work

    Projects that previously used a JS library purely for color manipulation (darken/lighten logic) can often remove that dependency entirely, improving load performance metrics that factor into search ranking signals.

Best Practices

Derive Interactive States (Hover, Active, Disabled) From Base Tokens Instead Of Hardcoding Them

This keeps every derived state automatically correct after a rebrand or theme change, eliminating a whole category of stale-color bugs that hardcoded hex values are prone to.

Default To oklch For Generating Systematic Tint/Shade Scales

Its perceptual uniformity produces visually smoother, more predictable results than sRGB when blending colors that are far apart on the color wheel.

Frequent Bugs

THE BUG

A hover state color looks correct after launch but becomes visually wrong after a brand color update.

THE FIX

The hover state was a separately hardcoded hex value instead of a color-mix() derived from the brand token — switch to deriving it so future token updates propagate automatically.

THE BUG

A generated tint/shade scale looks muddy or uneven in the middle of the range.

THE FIX

The mix was computed in srgb; switch to color-mix(in oklch, ...) for a perceptually smoother result across the scale.

Real-World Examples

A Full Button State Set Derived From One Token

A button component deriving its default, hover, and active background colors entirely from a single --color-brand custom property using color-mix().

:root { --color-brand: #FF0099; }
.btn { background: var(--color-brand); }
.btn:hover { background: color-mix(in srgb, var(--color-brand) 85%, black); }
.btn:active { background: color-mix(in srgb, var(--color-brand) 70%, black); }

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Hardcoding a second hex value for a hover state instead of deriving it

/* Wrong: separate, driftable value */ .btn:hover { background: #cc007a; } /* Correct: derived */ .btn:hover { background: color-mix(in srgb, var(--color-brand) 85%, black); }

The Solution //

Use color-mix() to derive the hover state from the same token as the base color, so they stay in sync automatically.

The Error //

Omitting the required color-space argument

/* Wrong: invalid syntax */ color-mix(red, blue); /* Correct */ color-mix(in srgb, red, blue);

The Solution //

color-mix() requires an explicit 'in <color-space>' declaration; it isn't optional.

Lesson Glossary

[01]color-mix()

A CSS function that blends two colors in a given color space.

Code Preview
color-mix(in srgb, red, blue)

[02]Color Space

The model used to interpolate between two colors (srgb, oklch, etc).

Code Preview
in oklch

[03]Mix Weight

The percentage controlling how much a color contributes to a blend.

Code Preview
red 70%

[04]Perceptual Uniformity

A color space property where equal numeric steps look equally different.

Code Preview
oklch

Continue Learning