What is a CSS gradient and why use one?
A CSS gradient is a special type of image (yes — image, not color) generated by the browser from a starting color, an ending color, and a transition rule. Defined in CSS Images Module Level 3, gradients let you create smooth color transitions for backgrounds, borders, and overlays without ever loading an image file. They're rendered at any resolution, scale infinitely without pixelation, animate cheaply, and weigh nothing on your bandwidth.
Three flavors cover ~99% of real-world gradient use:
- Linear gradient — colors transition along a straight line at any angle. The default for hero backgrounds, button fills, divider strokes, glow effects.
- Radial gradient — colors radiate outward from a center point. Used for spotlight effects, soft circular vignettes, dotted/textured backgrounds with
repeating-radial-gradient. - Conic gradient — colors sweep around a center point like a clock. Used for pie/donut chart visuals, color wheels, loading spinners.
All three can be combined, layered, and animated. Modern CSS even supports color-space-aware interpolation (linear-gradient(in oklch, red, blue)) which produces smoother color transitions through brighter perceived midpoints than the default sRGB blending.
Linear gradients — the workhorse
Linear gradients transition colors along a straight line. The angle defines the line direction; color stops define what color appears at what percentage of the way down the line.
/* Default: top → bottom */
background: linear-gradient(red, blue);
/* Specify angle (clockwise from up) */
background: linear-gradient(45deg, red, blue);
/* Specify side ("to bottom right" — clearest syntax) */
background: linear-gradient(to bottom right, red, blue);
/* Multi-stop with explicit positions */
background: linear-gradient(to right,
red 0%,
yellow 50%,
blue 100%
);
/* Hard stops (no transition between two colors) */
background: linear-gradient(to right, red 50%, blue 50%);
/* Modern: interpolate in OKLCH for smoother midpoint */
background: linear-gradient(in oklch, red, blue);
Common angle reference
| Angle | Direction | "to" syntax |
|---|---|---|
0deg | ↑ Bottom to top | to top |
45deg | ↗ Bottom-left to top-right | to top right |
90deg | → Left to right | to right |
135deg | ↘ Top-left to bottom-right | to bottom right |
180deg | ↓ Top to bottom (default) | to bottom |
270deg | ← Right to left | to left |
Radial gradients — for soft, circular effects
Radial gradients create elliptical or circular color transitions. The shape, size, and center are all customizable.
/* Default: ellipse centered, fades from inner to outer */
background: radial-gradient(red, blue);
/* Force circle */
background: radial-gradient(circle, red, blue);
/* Position the center */
background: radial-gradient(circle at top right, red, transparent);
/* Custom size */
background: radial-gradient(circle 200px at center, red, blue);
/* Spotlight effect on dark UI */
background: radial-gradient(
circle at 50% 30%,
rgba(0, 208, 132, 0.15) 0%,
transparent 50%
);
/* Repeating radial — for striped backgrounds */
background: repeating-radial-gradient(
circle,
#1a1d20 0px, #1a1d20 2px,
#14171a 2px, #14171a 4px
);
Sizing keywords
| Keyword | Meaning |
|---|---|
closest-side | Gradient ends at nearest box edge |
closest-corner | Gradient ends at nearest corner |
farthest-side | Gradient ends at furthest edge (default for ellipse) |
farthest-corner | Gradient ends at furthest corner (default for circle) |
Conic gradients — pie chart magic in pure CSS
Conic gradients sweep colors around a center point like the hands of a clock. Less common than linear/radial, but uniquely useful for pie/donut charts, color wheels, and progress rings without SVG.
/* Color wheel — full sweep through hues */
background: conic-gradient(
from 0deg,
red, yellow, lime, cyan, blue, magenta, red
);
/* Pie chart — three slices */
background: conic-gradient(
red 0deg 120deg,
blue 120deg 240deg,
green 240deg 360deg
);
/* Progress ring — 75% complete */
background: conic-gradient(
var(--accent) 0% 75%,
var(--bg3) 75% 100%
);
/* Angled checkerboard */
background:
conic-gradient(#000 90deg, #fff 0 180deg, #000 0 270deg, #fff 0)
0 0/40px 40px;
Combined with border-radius: 50%, conic gradients become circular pie charts with zero JavaScript and zero SVG. Combined with mask, they become donut charts. Browser support since 2021 (Chrome 69, Firefox 83, Safari 12.1) — safe for production.
Multi-stop & transparent gradients — the advanced patterns
Color stops with explicit percentages
background: linear-gradient(to right,
#ff0080 0%,
#ff8c00 25%,
#ffd700 50%,
#00d084 75%,
#00a8e8 100%
);
Transparent gradients for overlays
Combine a gradient with transparent stops to create vignettes, fades, and image overlays:
/* Image with bottom-fade-to-black overlay */
.hero {
background:
linear-gradient(to top, rgba(0,0,0,0.8), transparent 60%),
url('hero.jpg') center/cover;
}
/* Glassmorphism / frosted glass */
.glass {
background: linear-gradient(135deg,
rgba(255,255,255,0.1) 0%,
rgba(255,255,255,0.05) 100%
);
backdrop-filter: blur(10px);
}
Multiple gradients layered
CSS lets you stack gradients (and images) in a single background property, comma-separated. First listed = top layer.
background:
/* Top layer: subtle vignette */
radial-gradient(ellipse at center, transparent 50%, rgba(0,0,0,0.4) 100%),
/* Bottom layer: blue-to-purple fill */
linear-gradient(135deg, #667eea 0%, #764ba2 100%);
Modern color spaces — OKLCH gradients fix the "muddy middle"
By default, CSS interpolates gradient colors in sRGB color space. This produces a perceptually muddy gray at the midpoint between two saturated colors:
/* sRGB (default) — midpoint is dull gray-brown */
background: linear-gradient(red, blue);
/* OKLCH — perceptually uniform, midpoint is vibrant purple */
background: linear-gradient(in oklch, red, blue);
/* Other modern color spaces */
background: linear-gradient(in lch, red, blue); /* perceptual */
background: linear-gradient(in hsl shorter hue, red, blue); /* shortest hue path */
background: linear-gradient(in hsl longer hue, red, blue); /* longest hue path */
Browser support for in <color-space> syntax: Chrome 111+, Safari 16.2+, Firefox 113+ (mid-2023). Safe for modern audiences in 2026; provide an sRGB fallback for older browsers.
conic-gradient(in oklch longer hue, ...). The OKLCH path keeps perceived brightness uniform across all hues — your sRGB version always has dull blues and bright yellows.
CSS gradient performance
Gradients are GPU-accelerated in every modern browser, so a single static gradient costs essentially nothing to render. But three patterns can hurt performance:
- Animating gradient stops via CSS variables triggers repaints on every frame. Most browsers can't animate
background-imagedirectly. Useopacity/filteron a positioned overlay instead. - Layering 5+ gradients in a single element increases paint cost. The first 1–2 are free; the 5th adds noticeable cost on low-end mobile.
- Repeating gradients with very small repeat units (e.g. 1px stripes) force the browser to render large textures. Use SVG patterns for fine repeating textures instead.
Animating gradients the right way
/* WRONG — re-paints the whole gradient every frame */
@keyframes shift {
to { background: linear-gradient(45deg, blue, red); }
}
/* RIGHT — animate background-position on a wider gradient */
.animated {
background: linear-gradient(45deg, red, blue, green, red);
background-size: 400% 400%;
animation: shift 8s ease infinite;
}
@keyframes shift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
CSS gradient best practices
- Use OKLCH interpolation for any gradient with vivid colors. The default sRGB midpoint is depressing; OKLCH stays vivid.
- Always provide a fallback solid color.
background: red; background: linear-gradient(...);— for browsers that don't support the gradient, the solid color shows through. - Use percentages, not pixels, for color-stop positions. Gradients at
0% / 50% / 100%scale with the container; gradients at0px / 100px / 200pxonly look right at one width. - Test contrast on text overlaid on gradients. WCAG AA requires 4.5:1 contrast. A gradient that includes light colors needs a darkening overlay or text-shadow for readability.
- Don't stack 6+ gradients in one element. Layer in
::beforeand::afterpseudo-elements if you need many. Keeps paint cost manageable. - Avoid animating gradient stops or colors directly. Animate
background-position,opacity, ortransforminstead. - Use CSS variables for theme switching.
linear-gradient(var(--from), var(--to))lets you change the gradient by updating one variable. - For brand gradients, define them once in design tokens. Reuse via custom properties — the brand changes once, the whole site updates.
- Test on real low-end devices. 5+ gradient layers with
backdrop-filter: blur()can drop a $200 Android to 30fps. Profile before shipping. - Use repeating-* gradients for patterns. Stripes, checkerboards, dotted backgrounds — all possible with pure CSS, no SVG, no images.