# CSS gradient OKLCH interpolation for smoother blends

[Canonical HTML page](https://gradiently.design/guide/css-gradient-oklch)

Most dull, grey-middled gradients are not a colour problem but a maths problem. Two words, in oklch, change where the browser does the maths.

## The short version

- CSS gradients blend in sRGB by default when all their colours are written as hex, rgb() or hsl(), which often makes the middle of a blend dull or grey.
- Adding in oklch or in oklab to a gradient tells the browser to blend in a perceptual colour space, which keeps lightness even and colours clean.
- in oklab takes the straightest path between two colours, while in oklch travels around the hue circle and keeps saturation high.
- Hue keywords such as shorter hue, longer hue, increasing hue and decreasing hue choose which way an oklch gradient travels around the colour wheel.
- Browsers ignore declarations they cannot parse, so writing an sRGB gradient first and the oklch version after it is a safe fallback.

**CSS gradient OKLCH** interpolation means asking the browser to calculate a gradient's in-between colours in the OKLCH colour space rather than in sRGB. You add two words after the direction: `linear-gradient(90deg in oklch, #2563eb, #facc15)`. The result is a blend whose lightness changes evenly and whose middle stays vivid, instead of sagging into the grey, muddy band that plain sRGB blends are known for.

- sRGB (default for hex): `linear-gradient(90deg, #2563eb, #facc15)`
- in oklab: `linear-gradient(90deg in oklab, #2563eb, #facc15)`
- in oklch: `linear-gradient(90deg in oklch, #2563eb, #facc15)`

Blue to yellow three ways. sRGB passes through grey; oklab stays clean and neutral; oklch keeps full colour by travelling through teal and green.

## Why sRGB gradients go grey

sRGB was designed to encode screen colours efficiently, not to match how people see. Blending two sRGB colours means averaging their red, green and blue numbers, and halfway between a blue and a yellow is a set of middling numbers that looks grey. Its lightness also changes unevenly, so some blends bulge brighter or darker in the middle. The design side of this problem is in [muddy gradients](https://gradiently.design/guide/muddy-gradients).

Oklab and its cylindrical form, OKLCH, were designed so that equal steps in their numbers look like roughly equal steps to the eye. Blending in them keeps perceived lightness moving steadily, which is why gradients made this way look smoother and brighter at the same endpoints.

## The syntax: in oklch and in oklab

The interpolation method goes in the first argument, before or after the direction. It works in `linear-gradient()`, `radial-gradient()`, `conic-gradient()` and their repeating forms, and also in `color-mix()`. Your colour stops can stay in hex; only the maths changes.

```css
/* direction first or interpolation first: both are valid */
background: linear-gradient(135deg in oklch, #7c3aed, #f97316);
background: linear-gradient(in oklch 135deg, #7c3aed, #f97316);

/* works in the other gradient functions too */
background: radial-gradient(in oklab circle at 30% 30%, #22d3ee, #1e1b4b);
background: conic-gradient(in oklch from 90deg, #ef4444, #3b82f6, #ef4444);
```

Only the blend changes; the colour stops stay as written.

| Colour space | How it blends | Use it for |
| --- | --- | --- |
| `srgb` | Averages red, green and blue | Matching old designs exactly |
| `srgb-linear` | Averages physical light | Light mixing effects; midpoints look bright |
| `oklab` | Straight line through a perceptual space | Most blends, and any fade to white, black or grey |
| `oklch` | Around the hue circle at steady chroma | Vivid multi-hue blends, rainbows, sunsets |
| `hsl` | Around the hue circle, not perceptual | Colour wheels; lightness is uneven |

The spaces you are most likely to use. The [MDN color-interpolation-method page](https://developer.mozilla.org/en-US/docs/Web/CSS/color-interpolation-method) lists all of them.

## oklab or oklch: which to choose

Both are perceptual; they differ in the path they take. **Oklab** draws a straight line between the two colours, so the middle can lose some saturation when the ends are far apart on the colour wheel, but it never wanders through a hue you did not ask for. **OKLCH** keeps chroma, the colour's intensity, and walks around the hue circle, so the middle stays saturated but passes through the hues in between. Blue to yellow in oklch goes through green. Sometimes that is the point; sometimes it is a surprise.

- Pink to teal, in oklab: `linear-gradient(90deg in oklab, #db2777, #0891b2)`
- Pink to teal, in oklch: `linear-gradient(90deg in oklch, #db2777, #0891b2)`
- Indigo to white, in oklab: `linear-gradient(90deg in oklab, #1e1b4b, #ffffff)`
- Violet to orange, in oklch: `linear-gradient(90deg in oklch, #7c3aed, #f97316)`

Oklab stays on the direct path; oklch sweeps through the hues between its ends: pink to teal passes through violet and blue, violet to orange through magenta and red.

> **Fading to white, black or grey** Neutral colours have no real hue, so an oklch blend towards white or black can take an odd route. For fades to a neutral, use `in oklab`, or write the neutral end as a near-neutral with the same hue as the other end, such as `oklch(97% 0.02 290)`.

## Choosing the hue direction

Between any two hues there are two ways round the colour wheel. By default oklch takes the `shorter hue`. You can ask for `longer hue`, or force a direction with `increasing hue` or `decreasing hue`. The keyword goes straight after the colour space.

- Red to blue, shorter hue: `linear-gradient(90deg in oklch shorter hue, #ef4444, #3b82f6)`
- Red to blue, longer hue: `linear-gradient(90deg in oklch longer hue, #ef4444, #3b82f6)`

The short way from red to blue passes through magenta and violet. The long way passes through orange, yellow, green and cyan.

`longer hue` is the tidiest way to draw a spectrum: two stops instead of seven. It is also how you make a full [rainbow gradient](https://gradiently.design/guide/rainbow-gradient) whose colours all feel equally bright, which an sRGB rainbow never quite manages.

## Writing colours in oklch()

You can also write the stops themselves in OKLCH: `oklch(L C H)`, where L is lightness from 0% to 100%, C is chroma from 0 up to roughly 0.37, and H is the hue angle. Keeping L the same across stops gives a gradient of equal lightness, which is hard to do by eye in hex. [oklch.com](https://oklch.com) is a good picker for finding values.

```css
.band {
  /* same lightness and chroma, only the hue changes */
  background: linear-gradient(
    90deg in oklch,
    oklch(68% 0.17 300),
    oklch(68% 0.17 20),
    oklch(68% 0.17 70)
  );
}
```

Violet through coral to amber at one lightness: no stop jumps out as brighter than the others.

Equal lightness: violet, coral, amber: `linear-gradient(90deg in oklch, oklch(68% 0.17 300), oklch(68% 0.17 20), oklch(68% 0.17 70))`

The code above, rendered. Colours outside a screen's range are mapped to the nearest colour it can show.

## Browser support and fallbacks

Interpolation methods and `oklch()` colours are supported in current Chrome, Edge, Safari and Firefox. Browsers skip any declaration they cannot parse, so the fallback is simply to write the plain version first. Where the enhanced line is ignored, the sRGB gradient stays.

```css
.hero {
  background-color: #7c3aed;
  background-image: linear-gradient(135deg, #7c3aed, #f97316);
  background-image: linear-gradient(135deg in oklch, #7c3aed, #f97316);
}
```

Flat colour, then sRGB, then oklch. Each browser keeps the last line it understands.

If you want to go further, perceptual blends pair well with grain to prevent [gradient banding](https://gradiently.design/guide/gradient-banding), and with the stop and hint techniques in the [CSS linear gradient](https://gradiently.design/guide/css-linear-gradient) guide.

## FAQ

### What does in oklch do in a CSS gradient?

It makes the browser calculate the in-between colours in the OKLCH colour space, which keeps lightness even and colours saturated instead of blending through grey.

### Should I use oklab or oklch for gradients?

Use oklch for vivid blends between different hues, and oklab for fades towards white, black or grey, or when you do not want the blend to pass through extra hues.

### Why does my oklch gradient go through green?

OKLCH travels around the hue circle, and between blue and yellow the shorter way passes through green. Use `in oklab` for a direct path, or add a middle stop.

### Do I need to write colours in oklch() to use oklch interpolation?

No. Hex colours work fine with `in oklch`; only the blending changes. Writing stops in `oklch()` is useful when you want to control lightness precisely.

### What happens in browsers that do not support in oklch?

They ignore the whole declaration. Put a normal sRGB gradient on the line before it and those browsers keep that one.
