Skip to main content

CSS Gradient Generator

CSS gradients in both spaces, shown side by side.

Gradient

0° runs bottom to top, 90° left to right.

The two interpolations, side by side

OKLCH — perceptually even

sRGB — the usual result

Between two saturated hues the sRGB version passes through a washed-out middle, because it interpolates the red, green and blue channels independently and those are not perceptually even. Browser support for in oklch is good but not universal — keep a plain gradient as the fallback declaration above it.

Build a linear gradient and get the CSS — in OKLCH, and in sRGB for comparison. The two are rendered above each other so the difference is visible rather than asserted: between two saturated colours, the sRGB version passes through a washed-out middle that most people have stopped noticing because every gradient on the web has it.

01

Why use this tool?

See both at once

OKLCH and sRGB rendered together. The difference is obvious once you have looked at it.

Copy-ready CSS

Emits `in oklch` with a note about keeping a plain fallback above it.

Angle control

Any angle in fifteen-degree steps.

Honest preview

Rendered from sampled swatches, not a CSS gradient, so the comparison is accurate even in browsers that do not support `in oklch` yet.

02

How this css gradient generator works

A CSS gradient interpolates its stops channel by channel. In sRGB that means red, green and blue each move linearly and independently — and because none of those axes corresponds to perceived brightness or saturation, the result sags. Between a saturated red and a saturated blue, the midpoint loses roughly a third of its chroma. That washed-out middle is on almost every gradient on the web.

Adding `in oklch` to the gradient tells the browser to interpolate in a perceptually uniform space instead. The endpoints are unchanged; everything between them is different. It is a one-word change with a visible result, which is rare enough to be worth knowing about.

The preview here is rendered from forty-eight sampled swatches rather than from two CSS gradients, deliberately. Browser support for `in oklch` is good but not universal, and a browser without it would silently render both examples identically — showing you no difference and quietly destroying the point of the comparison. Sampling the colours in JavaScript means what you see is accurate everywhere.

03

How to use it

  1. Step 1: Choose two colours

    Pick or paste.

  2. Step 2: Set the angle

    0 degrees runs bottom to top, 90 left to right.

  3. Step 3: Copy the CSS

    Take the OKLCH version and keep a plain gradient declared above it as a fallback.

04

Example usage

A hero background
Two brand colours across a full-width block, where the sRGB version's grey middle is most visible and most damaging.
Button and card fills
Short gradients over small areas, where the difference is subtle but the CSS costs nothing extra.
Data visualisation
A continuous scale for a map or heat chart, where a desaturated midpoint reads as missing data rather than as a middle value.
05

Banding, and why large gradients look striped

Banding is the other gradient problem, and it is unrelated to the colour space. A standard display shows 8 bits per channel — 256 levels. Stretch a subtle gradient across 1,600 pixels and you may only have a few dozen distinct values to spread over that distance, so each one occupies a visible band. The eye is unusually good at spotting these edges, an effect called Mach banding, which exaggerates a boundary that is mathematically tiny.

Banding gets worse as the gradient gets subtler and larger. Two similar colours across a full-width hero is the worst case; two very different colours across a button is essentially immune. This is why a gradient that looks flawless in a small design comp develops stripes when it goes full-bleed on a large monitor, and why checking at final size matters.

The standard fix is dithering — adding a small amount of noise so the transition between levels is scattered rather than a clean edge. A subtle noise overlay, or a repeating SVG turbulence filter at low opacity, breaks up the bands convincingly at almost no cost. Switching to OKLCH does not solve banding, though it does mean the levels you have are spent more usefully.

06

Frequently asked questions

Is `in oklch` safe to use?

Support is good in current browsers but not universal. Declare a plain gradient first and the OKLCH one after it — browsers that do not understand the second will use the first, and browsers that do will use the better one.

Why does the preview use swatches instead of a real gradient?

Because a browser that does not support `in oklch` would silently render both examples identically, which would quietly destroy the entire point of the comparison. Sampling the colours in JavaScript means what you see is honest everywhere.

Can I add more than two stops?

Not yet. Two stops covers most cases and keeps the comparison legible; multi-stop support is on the list.

Why does my gradient have visible stripes?

That is banding, and it is a bit-depth limit rather than a colour space problem. Displays give 256 levels per channel, and a subtle gradient stretched over a large area does not have enough distinct values to fill it, so each one occupies a visible band. Subtle and large is the worst combination.

How do I fix banding?

Add noise. A low-opacity noise overlay or an SVG turbulence filter scatters the boundary between levels so the eye stops resolving it as an edge. Increasing the difference between the two colours also helps, since a wider range has more levels to work with across the same distance.

Which gradient angle should I use?

180 degrees — top to bottom — is the safe default, because it mimics how light usually falls and reads as unremarkable. Diagonal angles are more dynamic but interact badly with responsive layouts, since the angle is fixed while the box changes shape, so a gradient tuned on desktop can arrive nearly vertical on a phone.

07

Browse every tool in Colour Tools.