Short answer
Color interpolation is the process of producing intermediate colors between two or more stops. It happens in gradients, animations and the color-mix() function. The result depends entirely on which color space is used — sRGB, HSL, OKLab or OKLCH will each produce visibly different middle colors.

The interpolation problem

Given two colors, what color lies halfway between them? The answer is not obvious. "Halfway" means different things depending on how you describe each color numerically. If you write the colors in sRGB, halfway is the arithmetic midpoint of three channel values. If you write them in OKLab, halfway is the perceptual midpoint. These are usually not the same color.

This is why the same two stops can produce very different gradients in different tools — and why color-mix() requires you to specify the interpolation space.

How different spaces interpolate

SpaceBehaviorResult
sRGB Linear midpoints of R, G and B channels Fast; muddy mid-tones between distant hues
Linear sRGB Linear midpoints after gamma decoding Physically correct; still muddy for distant hues
HSL Hue rotates, S and L interpolate Bright middle for analogous hues, wrong direction for complementary
OKLab Perceptually uniform linear interpolation Smooth and consistent for all hue pairs
OKLCH Hue rotates, C and L interpolate Smooth and predictable — best for gradients with vivid mid-tones

Why sRGB gradients look muddy

Consider a gradient from blue to yellow in sRGB. At the midpoint, the RGB values average to a mid-gray — because blue is (0, 0, 255) and yellow is (255, 255, 0). The average is (127, 127, 127). That is a muted gray, not a color that feels halfway between blue and yellow.

Interpolate the same pair in OKLCH and the result passes through a rich green-cyan. This is because OKLCH interpolates hue, chroma and lightness as separate dimensions, so the hue rotates from blue to yellow without losing saturation or lightness.

Hue interpolation — shortest path

When interpolating in any polar space (HSL, LCH, OKLCH), the hue is an angle. Going from 10° to 350° could be a 20° counter-clockwise rotation or a 340° clockwise one. Browsers and libraries choose the shortest path by default — the 20° option — which produces a natural transition.

From 10° to 350°
  direct difference: 350 − 10 = 340°
  shortest: 340 − 360 = −20° (i.e. rotate counter-clockwise)

Most libraries clamp Δh to [−180°, +180°] to force the shortest path.

CSS: color-mix() and gradient hints

Modern CSS lets you specify the interpolation space directly.

CSS
/* color-mix() with explicit interpolation space */
background: color-mix(in oklab, blue, yellow);
color: color-mix(in srgb, red 40%, white);
border-color: color-mix(in oklch, #4f46e5, black 20%);

/* Gradient interpolation hint */
background: linear-gradient(in oklch, blue, yellow);
background: radial-gradient(in oklab, red, green, blue);

/* Long interpolation across the hue wheel */
background: linear-gradient(in oklch longer hue, red, magenta);

Practical examples

Blue to yellow

sRGB — muddy gray midpoint

OKLCH — smooth green-cyan midpoint

Red to green

sRGB — muddy brown midpoint

OKLCH — vivid yellow midpoint

Which space should I use?

TaskRecommended space
Gradients between distant huesOKLab or OKLCH
Gradients between similar huessRGB is fine
UI state transitionsOKLab or OKLCH for consistent perceived lightness
Icon and brand system blendingOKLCH for hue control
Print productionLab (industry standard for color science)
Matching a legacy toolsRGB to match the browser default

Continue reading

Frequently asked questions

What is color interpolation?

Color interpolation is the process of producing intermediate colors between two or more stops. It happens in gradients, animations, opacity fades and the CSS color-mix() function. The colors you get in between depend entirely on which color space is used.

Why do gradients look muddy in sRGB?

Because sRGB is not perceptually uniform. Interpolating complementary or distant hues in sRGB passes through darker, less saturated values, producing a muddy or grayish middle. Interpolating in OKLab or OKLCH avoids this.

What is the best space for interpolation?

OKLab is generally the best choice — it is perceptually uniform and its Cartesian form avoids hue-rotation issues. OKLCH is a good second choice if you want to control hue and chroma separately. sRGB remains the browser default and is fine for closely-related colors.

How do I specify interpolation in CSS?

Use the color-mix() function with an explicit space, such as color-mix(in oklab, blue, red). For gradients, use the interpolation hint: linear-gradient(in oklch, red, blue).