Mastering CSS Gradients With Modern Color Spaces and Interpolation

CSS gradients now support color interpolation in oklch, hsl, and sRGB, producing visibly different results from the same color stops with a medium paint cost.

You are staring at a gradient that goes from #ff0000 to #0000ff and it looks muddy. The midpoint is a washed-out purple that you did not choose. The transition feels flat. That is not a failure of your design eye. It is a failure of the default color space. Every gradient you have ever written in CSS has been interpolated in sRGB by default. sRGB is perceptually uneven, so the same numerical step between two colors looks different depending on where you are in the spectrum. CSS gradients fix this by letting you choose the color space in which the interpolation happens, and the syntax has just reached Baseline.

The color interpolation method is a single keyword placed inside the gradient function, after the color stops. It changes everything about how the gradient looks. The syntax is linear-gradient(red, blue, in oklch) or linear-gradient(in oklch, red, blue). The keyword can be in srgb, in hsl, in oklch, in oklab, in lab, in lch, or in display-p3. The in oklch value is the one you want for most work. oklch is perceptually uniform: a change in the lightness or chroma values produces a change in perceived color that matches the numerical change. The default remains in srgb, which is why your gradients have looked the way they have since 2011. The color-interpolation-method syntax is newly available in all major engines as of the 2026 Baseline update. The source for that is the web-platform-tests repository and the MDN Baseline dashboard. Here is the difference, side by side, in one code sample you can run today:

.gradient-comparison {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

.gradient-comparison div {
  height: 200px;
  border-radius: 8px;
}

.srgb {
  background: linear-gradient(to right, #ff0000, #0000ff);
}

.hsl {
  background: linear-gradient(to right, #ff0000, #0000ff, in hsl);
}

.oklch {
  background: linear-gradient(to right, #ff0000, #0000ff, in oklch);
}

The first block uses the default sRGB interpolation, the second forces HSL, and the third forces oklch. The sRGB version has a grayish-purple midpoint. The HSL version swings through a bright magenta that is not between the two endpoints at all. The oklch version produces a purple that is visually the midpoint you would expect from the two colors. The method is not a filter; it is a change to the math that generates every intermediate color.

CSS Gradient Interpolation: What the Syntax Actually Does

Where The Keyword Goes

The color interpolation method is not just for linear fills. It applies to radial-gradient, conic-gradient, and the repeating variants of all three. The keyword goes in the same position, after the color stop list or before it, and the effect is consistent: it changes the path the gradient takes through color space.

How Each Space Behaves

In sRGB, the path is a straight line in the red-green-blue cube. That is why you get that muddy midpoint. In HSL, the path is a straight line in the hue-saturation-lightness cylinder. That is why the hue can swing through colors that are not between the endpoints. In oklch, the path is a straight line in the perceptually uniform oklch cylinder, so lightness and chroma change at the rate your eye expects.

The Hack You Can Drop

The practical result is that you can now write a gradient that goes from a warm red to a cool blue and get a purple that actually looks like a purple, not a desaturated gray. This one syntax saves you from the old hack of adding a third color stop at the midpoint to compensate for the sRGB distortion. That hack is now obsolete for new work. Stop using it.

.radial-oklch {
  background: radial-gradient(circle at center, #ff0000, #0000ff, in oklch);
}

.conic-oklch {
  background: conic-gradient(from 0deg, #ff0000, #0000ff, #ff0000, in oklch);
}

.repeating-oklch {
  background: repeating-linear-gradient(45deg, #ff0000 0 10px, #0000ff 10px 20px, in oklch);
}

These three examples show the same syntax applied to the other gradient types. The radial version interpolates through the circle, the conic version wraps the interpolation around the angle, and the repeating version uses the interpolation method for the hard stops as well. Note that the in oklch keyword comes after the color stop list in all three, which is the position the specification currently recommends for readability. It is also valid before the first color stop.

Gradient Color Space Oklch: Why Perceptual Uniformity Matters

A Cylinder You Can Trust

Oklch is a cylindrical color space. It describes colors in terms of lightness, chroma, and hue, much like HSL, but it is designed to be perceptually uniform. A change of 10 units in lightness looks the same to your eye whether you are at the dark end or the light end of the range. HSL does not have this property. A change of 10 units in lightness near the top of the cylinder looks much smaller than the same change near the bottom. The same problem exists for chroma and hue.

The Midpoint Problem, Solved

When you interpolate in oklch, the gradient moves through colors that are evenly spaced perceptually. The midpoint between red and blue is a purple that is visually halfway between them. When you interpolate in hsl, the midpoint can be a bright magenta that is not between the endpoints at all, because the hue path swings through the magenta region of the cylinder.

When To Reach For Oklch

Oklch is the correct choice for any gradient where you want the intermediate colors to be a faithful blend of the endpoints. For gradients that are purely decorative, like a subtle background wash from one shade of gray to another, the difference is small. The default sRGB is fine there. But for any gradient where the colors matter, such as a data visualization heatmap or a brand gradient, oklch is the only choice that gives you a neutral midpoint. The old default, sRGB, has been the source of countless muddy gradients since 2011. The fix is a single keyword.

Conic Gradient CSS: The Third Gradient Type, Now With Interpolation Control

How A Conic Gradient Works

The conic gradient is the youngest of the three gradient types, having reached Baseline widely available in September 2023. Unlike linear and radial gradients, which interpolate along a line or a circle, the conic gradient interpolates around an angle. It starts from a defined from angle and sweeps around a full circle. The syntax is conic-gradient(from <angle>, <color-stop-list>). Reach for it when you need a color wheel, a pie chart, or a gauge.

Fixing The Conic Midpoint

The default interpolation is still sRGB, so a conic gradient from red to blue produces the same muddy midpoint as the linear version. Adding in oklch to a conic gradient fixes that. The result is a color wheel that transitions evenly through perceptually spaced hues. The conic gradient also supports the same color stop and color hint syntax as the other two types. Place stops at specific angles and add hints to bias the transition.

Repeating Conic Patterns

The repeating conic gradient, repeating-conic-gradient, repeats the same sweep around the circle. This is useful for striped patterns or speedometer backgrounds. For all of these, the interpolation method keyword is placed after the color stop list. It applies to every sweep of the repeating version.

Gradient Fallback Solid Color: Two Levels of Safety

Level One: The Solid Color

The first rule of using gradients in CSS is to declare a solid background color before the gradient. This is the fallback for engines that do not support gradients at all, which means any engine older than 2011 for linear and radial gradients, or older than 2023 for conic gradients. The pattern is straightforward: declare the background color first, then the gradient. The color is used if the gradient is unsupported.

Level Two: The Interpolation Fallback

The second rule is newer. For engines that support gradients but not the color interpolation method, you need a separate fallback. The in oklch syntax is a relatively new addition. While it is now Baseline, there are still engines in the field that do not support it. Write the gradient without the interpolation method first, then the same gradient with it. The engine will use the version it understands.

Explicit Control With @supports

The third rule is to guard the interpolation method with @supports if you need to be certain. Here is the complete fallback pattern:

.element {
  /* Fallback for browsers with no gradient support at all */
  background-color: #7f007f;

  /* Fallback for browsers that support gradients but not the interpolation method */
  background-image: linear-gradient(to right, #ff0000, #0000ff);

  /* The modern version, used only if supported */
  background-image: linear-gradient(to right, #ff0000, #0000ff, in oklch);
}

@supports (background: linear-gradient(in oklch, red, blue)) {
  .element {
    background-image: linear-gradient(to right, #ff0000, #0000ff, in oklch);
  }
}

The @supports block is not strictly necessary if you use the fallback order above, because the engine will ignore the in oklch version if it does not understand it and use the earlier declaration. But @supports gives you explicit control. Use it when you want a different gradient entirely when the interpolation method is unavailable. The solid color fallback is the most important one. Omitting it is the number one mistake that causes invisible text or elements in older engines.

What the Paint Cost Is and When It Matters

Why It Is Medium

The paint cost of using a gradient with a color interpolation method is medium. Use that qualitative rating when estimating the impact of a gradient on your page’s rendering performance. A gradient, any gradient, is painted by the engine’s rasterizer. It is more expensive than a solid color, which is a single fill. The cost of the interpolation method itself is negligible. The difference between sRGB and oklch is a few extra floating-point operations per pixel, which is nothing compared to the cost of rasterizing the gradient shape.

When The Cost Is Paid

The medium rating comes from the fact that a gradient covers a large area, and the engine must compute a color for every pixel in that area. For a full-screen gradient, that is millions of pixels. The good news is that gradients are painted once and cached if the element does not change. The bad news is that if you animate a gradient, it repaints on every frame. It does not run on the compositor. The compositor is the engine thread that handles transforms and opacity animations without touching the main thread.

How To Animate Without Jank

Animating a background gradient is not compositor-eligible. It runs on the main thread, and you will see jank on low-powered devices. If you need an animated gradient, animate a transform or opacity of a static gradient element instead. Or use a pre-rendered canvas if the gradient is complex. The medium paint cost is a warning, not a prohibition. Know what it costs before you put a full-screen animated gradient on your landing page.

The Practical Workflow: What to Write, What to Test, What to Skip

Choose The Color Space

When you are building a gradient today, the workflow is three steps. First, choose the color space deliberately. For most work, that is oklch. It is perceptually uniform and gives you the visual result you are designing for. For a subtle transition between two very similar colors, sRGB is fine and saves you nothing to change. For a brand gradient where the intermediate colors matter, oklch is the only honest choice.

Write The Fallback Order

Second, write the fallback order: solid color first, then the gradient without the interpolation method, then the gradient with it. This is three lines of CSS and it covers every engine from 2011 to today.

Test And Skip

Third, test the gradient in an engine that does not support the interpolation method. That means an older Safari or an engine with the feature disabled. The @supports guard is your friend here. It lets you provide a completely different gradient for those engines, not just the same gradient with a different midpoint. What you should skip is the old practice of adding a manual midpoint color stop to compensate for sRGB distortion. That hack is now obsolete. It produces worse results than using oklch. The only time you should keep it is if you are supporting an engine that does not support the interpolation method and you cannot use @supports for some reason. That is a vanishingly rare situation in 2026.

Frequently Asked Questions

Does the color interpolation method work on all gradient types? Yes. The in oklch syntax applies to linear-gradient, radial-gradient, conic-gradient, and all three repeating variants. The keyword goes after the color stop list in every case.

What is the performance difference between sRGB and oklch interpolation? The difference is negligible, well under one millisecond per frame for a typical gradient. The paint cost is dominated by the gradient shape, not the color space.

Can I animate a gradient with oklch interpolation? Yes, but it repaints on every frame and runs on the main thread, not the compositor. This is medium cost and can cause jank. Animate transform or opacity of a static gradient instead.

Do I still need a solid color fallback if I use @supports? Yes. The @supports guard only tests for the interpolation method. An engine that does not support gradients at all will not understand linear-gradient in the @supports test, so you still need the solid color first.

CSS Gradients Modern Color Spaces: The Performance Budget and the Compositor

Set A Budget First

CSS gradients modern color spaces are not free. Set a performance budget before you design. The paint cost is medium. A single gradient on a page is fine. A page full of animated gradients will struggle on a mobile device.

The Compositor Gap

The compositor is the thread that handles smooth scrolling and transform animations. Gradients do not run on it. When you animate a gradient, you force the main thread to rasterize the new gradient every frame. That competes with your JavaScript and layout work. The result is dropped frames that feel like stutter.

The Static Rule

The rule of thumb is straightforward. If a gradient is static, it is painted once and cached. The medium cost is paid once. If a gradient is animated, you pay the medium cost every frame. Question whether the visual effect is worth it. There is an alternative: create the gradient on a canvas and animate the canvas in a transform, which is compositor-eligible. That is more work, but it is the only way to get a smooth animated gradient on a low-powered device. For most pages, a static gradient with oklch interpolation is the right choice. Reserve animated gradients for moments when they are truly the point of the design.

The Failure Case: When the Normal Route Is Closed

Diagnose The Muddy Midpoint

The failure case for a gradient is not an engine that does not support it. It is a gradient that looks wrong and you do not know why. The most common symptom is a muddy midpoint, which you now know is caused by sRGB interpolation. The second most common symptom is a gradient that has a hard transition where you expected a smooth one. That is caused by color stops that are out of ascending order or overlap.

Fix It Fast

The fix for the muddy midpoint is to switch to oklch. The fix for the hard transition is to check your color stop positions and make sure they are in ascending order. The third failure case is a conic gradient that starts at the wrong angle. This is caused by confusing the from angle with the CSS angle convention where 0deg points upward, not rightward. Remember: conic gradients start at the top and sweep clockwise.

The Three-Check Debug Routine

If you are debugging a gradient that looks wrong, the first thing you do is add in oklch to it and see if the midpoint improves. The second thing you do is remove the gradient entirely and check the solid color fallback. This tells you whether the gradient is rendering at all. The third thing you do is look at the color stops and verify they are in ascending order. These three checks solve ninety percent of gradient problems.

The Comparison Table: sRGB, HSL, and oklch for Gradient Interpolation

Property sRGB (default) HSL oklch
Perceptual uniformity No No Yes
Midpoint between red and blue Muddy gray-purple Bright magenta Neutral purple
Gamut coverage sRGB only sRGB only Display P3 and beyond
Syntax required None (default) in hsl in oklch
Browser support Baseline since 2017 Baseline since 2026 Baseline since 2026
Paint cost Medium Medium Medium
Animatable Yes, main thread Yes, main thread Yes, main thread

The table shows the three spaces you are likely to choose from. sRGB is the default and it is fine for subtle transitions. HSL is almost never the right choice for interpolation because the hue path swings through colors that are not between the endpoints. oklch is the choice for any gradient where the intermediate colors matter, and it is the only one of the three that is perceptually uniform. The gamut coverage row is important: oklch can represent colors in Display P3, which is the wider color space that modern displays support. If you are designing for a wide-gamut display, sRGB gradients are limited to the sRGB gamut. oklch lets you use the full range of the display.

Who Should Use This and Who Should Not

The Right Reader

This guide suits the working front-end developer who writes CSS daily and needs to know what shipped, what is safe to use, and what the fallback is. It suits the full-stack engineer who touches CSS occasionally and needs a reliable reference for the modern way. It suits the performance-conscious developer who needs to understand what a declaration costs in layout, paint, and composite. It suits the technical writer who needs accurate, sourced statements about CSS features.

Send Them Elsewhere

It does not suit someone learning to code from zero. That reader should go to web.dev/learn/css or the MDN CSS first-steps guide before returning here. It does not suit someone debugging a React state bug, because this is a CSS page, not a JavaScript page. It does not suit someone looking for CSS-in-JS library comparisons, because that is a JavaScript tooling question. The subject of CSS gradients with modern color spaces is a precise tool for a precise audience. That audience is anyone who writes CSS and cares about how their gradients look and how much they cost.