/

CSS Gradients for React: Mesh, Aurora and the OKLCH Fix

The gradient shapes that recur across the catalogue, and the colour-space detail that explains why a two-colour gradient goes muddy in the middle.

Serafim Korablev
Serafim Korablev
@korablev

A gradient is the cheapest way to make a screen look designed and the easiest way to make it look generic, and the difference between the two is usually two decisions: how many hues are in it, and what colour space the browser interpolated through.

140 public components on 21st have "gradient" in the name. Below are the shapes that recur, and the colour-space detail that explains why a hand-written gradient often looks muddy in the middle when the same two colours look fine at the ends.

The animated background

The largest group. Aurora Background by Manu Arora is the most-bookmarked gradient in the catalogue: soft coloured light drifting behind the content. Background Gradient Animation by the same author is the blob version where the colours move against each other, and Animated Gradient Background by hammamikhairi is the plainer take.

Animated Gradient by tom_ui exposes presets and a customisable swirl, which is the practical difference between a component you keep and one you fork.

Two costs to know. A gradient animated by moving background-position repaints a full-screen element on every frame; one built from a few blurred radial blobs on the compositor is cheaper. And a full-screen animated background is motion, so it needs a prefers-reduced-motion path that renders a still frame.

The gradient border

The effect that shows up on every second landing page: a card with a moving coloured edge. Animated Gradient Border by Hossain Jahed is the reference implementation.

The technique worth knowing is background: linear-gradient(...) border-box with a solid padding-box layer on top, or a ::before at inset: -1px behind the card. Both beat the old approach of a wrapper div with padding, because they survive a border radius without the corners going wrong.

Text and small surfaces

Gradient Text by Ali Imam is the background-clip: text pattern. Gradient Shimmer by Mona Biasia sweeps a multi-stop gradient across a headline with no dependencies, and Gradient Button is the animated-edge button.

The accessibility note that gets ignored: gradient text is text with a variable contrast ratio. If the gradient runs from a dark colour to a light one over a light background, part of the word fails contrast even though the screenshot looks fine. Check the lightest stop against the background, not the average.

Mesh and dots

Gradient Dots by Efferd is a field of small coloured dots that shift and cycle, and Animated Gradient With SVG by danielpetho combines a multi-colour gradient with SVG elements. Both are the "mesh" look without a WebGL context, which makes them the sensible default when the gradient is decoration rather than the product.

The colour space, which is the actual craft

This is the part that separates a gradient that looks expensive from one that looks like a default.

A CSS gradient interpolates between its stops. By default that happens in sRGB, which passes through a desaturated middle for many hue pairs: blue to yellow goes through grey, and red to green goes through a muddy brown. It is not your colour choice, it is the maths.

Modern CSS lets you say which space to travel through:

css

in oklch interpolates through a perceptually uniform space, which keeps chroma up through the middle and produces the smooth, saturated ramp that design tools show you. in oklab is the same idea without the hue path, and longer hue on a polar space takes the scenic route round the colour wheel when you want a rainbow rather than a blend.

Three practical follow-ons. Two-stop gradients with hues far apart benefit most, and are exactly the ones that look muddy in sRGB. Banding on a large flat gradient is fixed with a faint noise overlay, not with more stops. And OKLCH lets you build a whole palette by holding lightness and chroma while rotating hue, which is how a set of gradients ends up looking like a system instead of a collection.

Where else to look

The honest list of alternatives, because the answer is not always us:

SourceBest forTrade-off
Plain CSSEverything static, plus in oklch interpolationYou are writing the animation yourself
Paper ShadersMesh gradients and grain with a real shaderA WebGL context and a runtime
Tailwind CSSbg-linear-to-r, bg-radial and arbitrary stops in markupThe animated versions are still yours
21st gradient builderGenerating the CSS visually and copying it outA generator rather than a component
21stAurora backgrounds, animated borders, dot fields, gradient textQuality varies by author, so preview before you take it

Taking one

Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:

bash

That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue. The 21st MCP covers the same ground without leaving the editor: ask Claude, Cursor or Codex for a gradient, get the previews inline, and let the agent write the file.

Browse gradient components →

Frequently asked

Why does my CSS gradient look grey in the middle?
Because it is interpolating in sRGB, which passes through a desaturated midpoint for many hue pairs: blue to yellow goes through grey and red to green through brown. Add an interpolation space, as in linear-gradient(in oklch, ...), and the ramp keeps its chroma through the middle. It is a maths problem, not a colour-choice problem.
What is the difference between oklch and oklab in a gradient?
Both are perceptually uniform. OKLCH is polar, so it has a hue angle and the interpolation travels around the colour wheel, which also lets you ask for the longer hue path when you want a rainbow. OKLAB is cartesian and blends without a hue path, which gives a more direct mix between two colours.
Are animated gradient backgrounds expensive?
The implementation decides. Animating background-position on a full-screen element repaints it on every frame; a few blurred radial blobs moved with transforms stay on the compositor and cost far less. Either way it is motion, so it needs a prefers-reduced-motion path that renders a still frame.
How do you fix banding in a large gradient?
Add a faint noise or grain overlay rather than more colour stops. Banding comes from 8-bit quantisation across a large area, and extra stops do not add precision. A very low-opacity noise texture breaks the bands up and costs one small image or one SVG filter.

Published

Aug 20, 2026

Read time

5 min

Tags

GuideGradientsCSSColor

Share