How it works
A CSS gradient is an image the browser draws from a list of color stops. It goes anywhere an image goes, usually background:
background: linear-gradient(120deg, #6366f1 0%, #ec4899 100%);Three kinds of gradient
- Linear blends along a line.
0degpoints up and angles turn clockwise, so90degruns left to right. - Radial blends outward from a center. A
circlekeeps its proportions; anellipsestretches with the box. - Conic blends around a center, like a color wheel. Make the first and last stops the same color to hide the seam.
Color stops
Each stop is a color and a position. Between two stops the browser blends; before the first and after the last it holds the color.
Two stops at the same position give a hard edge instead of a blend, which is what the "Hard split" preset does:
background: linear-gradient(135deg, #0ea5e9 50%, #0f172a 50%);Why the middle sometimes looks grey
By default gradients blend in sRGB, which doesn't match how we perceive color. Between two opposite hues, such as blue and yellow, the channels meet at a dull grey. You can ask for a different color space:
background: linear-gradient(90deg in oklch, #2563eb 0%, #facc15 100%);- sRGB is the default and the most widely supported, and it's fine for similar hues.
- OKLab is perceptually even, so brightness changes smoothly and midpoints look natural.
- OKLCH travels around the hue wheel. It stays saturated, but passes through hues neither end has.
A browser ignores a declaration it can't parse, so the CSS output puts a plain sRGB line first as a fallback. Tailwind classes are a single value and have no such fallback.
Fading to transparent
Fade to the same color with zero opacity, as the "Fade out" preset does. It's the clearest way to write a scrim over an image:
background: linear-gradient(180deg, rgb(15 23 42 / 1) 0%, rgb(15 23 42 / 0) 100%);Recipes
Gradient text
Paint the gradient as the background, clip it to the glyphs and make the text itself transparent:
.title {
width: fit-content;
background: linear-gradient(90deg, #6366f1, #ec4899);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}Keep background-clip after background: the shorthand resets it. width: fit-content makes the gradient span the text rather than the whole line.
Gradient border with rounded corners
border-image ignores border-radius, so use two background layers instead. The first fills the padding box, the second shows through the transparent border:
.card {
border: 2px solid transparent;
border-radius: 12px;
background:
linear-gradient(#18181b, #18181b) padding-box,
linear-gradient(120deg, #6366f1, #ec4899) border-box;
}The first layer has to be opaque, or the border gradient shows through the card.
Stripes
repeating-linear-gradient loops its list of stops. Use lengths rather than percentages, and give each color two positions so the edges stay hard:
background: repeating-linear-gradient(45deg, #0f172a 0 10px, #1e293b 10px 20px);Animated gradients
Browsers don't transition between two gradient images, so animate something the gradient depends on. The simplest option is an oversized background that slides. Matching first and last colors make the loop seamless:
.banner {
background: linear-gradient(90deg, #6366f1, #ec4899, #6366f1);
background-size: 200% 100%;
animation: slide 4s linear infinite;
}
@keyframes slide {
to { background-position: -200% 0; }
}To rotate a gradient, register its angle with @property so the browser knows how to interpolate it:
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.spinner {
background: conic-gradient(from var(--angle), #6366f1, #ec4899, #6366f1);
animation: spin 3s linear infinite;
}
@keyframes spin {
to { --angle: 360deg; }
}Both repaint on every frame, so keep them to small areas and turn them off under prefers-reduced-motion.