CSS Gradients: Linear, Radial, and Conic Explained

- CSS gradients in one minute
- How does linear-gradient() work?
- How does radial-gradient() work?
- How does conic-gradient() work?
- Which CSS gradient should you use?
- How do you stack and repeat gradients?
- How do color interpolation spaces change a gradient?
- How do you animate a CSS gradient reliably?
- Which background box does a gradient fill?
- What accessibility and rendering checks matter?
CSS gradients in one minute
A CSS gradient is a browser-generated image that blends two or more color stops. Use linear-gradient() for color along a straight line, radial-gradient() for color spreading from a point, and conic-gradient() for color sweeping around a point. Each function also has a repeating form. The CSS Images specification defines the geometry; the stops define where each color is exact and how the browser fills the space between them.
.linear { background: linear-gradient(to right, #6a11cb, #2575fc); }
.radial { background: radial-gradient(circle, #6a11cb, #2575fc); }
.conic { background: conic-gradient(from 0deg, #6a11cb, #2575fc); }
A gradient is an <image>, not a color. That distinction matters: it works in image-valued properties such as background-image, border-image, and mask, but not in background-color. It has no natural dimensions, so the property using it supplies the gradient box. MDN classifies the core gradient type as widely available, including current Chrome, Edge, Firefox, and Safari releases. Test the exact syntax you use, especially newer color-interpolation options, against the browsers in your support matrix.
How does linear-gradient() work?
linear-gradient() creates a gradient line through the box. Its first optional argument sets the line direction; the remaining arguments are color stops.
.hero {
background: linear-gradient(to bottom right, #ff512f, #dd2476);
}
Keywords and angles are different controls
- Keywords such as
to top,to right, andto bottom leftpoint toward a side or corner and adapt to the box proportions. - Angles such as
45deg,0.25turn, and3.14radset a fixed direction.0degpoints up, angles increase clockwise,90degpoints right, and180degpoints down.
On a square, to top right and 45deg appear equivalent. On a wide rectangle they diverge: the keyword aims toward the corner, while the angle remains 45 degrees. This is the CSS gradient-line geometry sometimes called “magic corners.”
.keyword { background: linear-gradient(to top right, #000, #fff); }
.angle { background: linear-gradient(45deg, #000, #fff); }
With no direction, a linear gradient runs from top to bottom.
Color stops, hard edges, and hints
A stop position says where a color must be exact. Omit positions and the browser distributes the stops automatically. Give one color two positions to make a solid band:
.stripes {
background: linear-gradient(
to right,
#6a11cb 0% 50%,
#2575fc 50% 100%
);
}
The double-position form #6a11cb 0% 50% is shorthand for two stops of the same color. Adjacent colors meeting at 50% create a hard edge, useful for flags, split backgrounds, and progress bars.
A bare position between colors is a transition hint, not another stop:
.biased-blend {
background: linear-gradient(to right, #f00, 20%, #00f);
}
Here the 50% blend between red and blue occurs at 20% of the gradient line. The transition remains smooth, but its balance shifts. The color-stop algorithm specifies both hard stops and hints.
How does radial-gradient() work?
radial-gradient() sends color outward from a center. Its prelude can set a shape, size, and position before the stop list:
.glow {
background: radial-gradient(
circle at center,
#ffd200,
#f7971e 70%
);
}
- Shape is
circleorellipse;ellipseis the default. - Size may be explicit or use
closest-side,closest-corner,farthest-side, orfarthest-corner. The default ending shape isfarthest-corner. - Position follows
at, using values such ascenter,top left, or30% 70%.
For a contained spotlight, set a radius and fade to transparent:
.spotlight {
background: radial-gradient(
circle 120px at 30% 40%,
rgb(255 255 255 / 90%),
rgb(255 255 255 / 0%) 100%
);
}
The 120px radius fixes the circle size. The transparent final stop prevents an abrupt visible boundary.
How does conic-gradient() work?
conic-gradient() measures stop positions around a center, like marks around a dial. That makes it useful for progress rings, loading indicators, color wheels, and pie-shaped decoration.
.pie {
background: conic-gradient(
#e63946 0% 25%,
#f1faee 25% 50%,
#a8dadc 50% 75%,
#457b9d 75% 100%
);
border-radius: 50%;
}
The four sectors cover 0–25%, 25–50%, 50–75%, and 75–100%. border-radius: 50% makes the box circular. Change the starting angle and center with from 90deg at 50% 50%.
Do not let colored sectors carry data by themselves. A conic-gradient chart is only paint: give the surrounding HTML an accessible label and present the values in text or a table too. Color alone must not be the only way a reader distinguishes categories under WCAG 2.2 Success Criterion 1.4.1.
A hue wheel can use HSL stops:
.wheel {
background: conic-gradient(
hsl(0 100% 50%),
hsl(60 100% 50%),
hsl(120 100% 50%),
hsl(180 100% 50%),
hsl(240 100% 50%),
hsl(300 100% 50%),
hsl(360 100% 50%)
);
border-radius: 50%;
}
Which CSS gradient should you use?
| Function | Colors travel | Useful for | Default geometry |
|---|---|---|---|
linear-gradient() |
Along a straight line | Backgrounds, buttons, overlays, stripes | Top to bottom |
radial-gradient() |
Outward from a point | Spotlights, glows, vignettes, orbs | Centered ellipse to farthest corner |
conic-gradient() |
Around a point | Progress rings, sectors, color wheels | From 0deg at center |
Choose by geometry. If the design language is “across,” start linear. If it is “outward,” start radial. If it is “around,” start conic.
How do you stack and repeat gradients?
Separate background images with commas. The first image is painted closest to the user, so transparency reveals the layers below it:
.layered {
background:
linear-gradient(rgb(0 0 0 / 60%), rgb(0 0 0 / 60%)),
radial-gradient(circle at 20% 20%, #ff8a00, transparent 40%),
linear-gradient(120deg, #1a2980, #26d0ce);
}
To darken a photo, put the translucent gradient before url(...). It is still necessary to test text contrast over the complete rendered result; an overlay value such as 60% is not, by itself, proof of compliance.
Repeating functions repeat the interval represented by the stop list:
.barber-pole {
background: repeating-linear-gradient(
45deg,
#ffcc00 0 20px,
#222 20px 40px
);
}
This pattern repeats every 40px. Two transparent repeating gradients set 90 degrees apart can form a grid. Repeating radial and conic gradients follow the same principle, but repeat along their radius or angle.
How do color interpolation spaces change a gradient?
Two gradients can use identical endpoints and still produce different midpoints. CSS Images Level 4 allows an interpolation method inside the function. For example:
.legacy-mix {
background: linear-gradient(in srgb to right, #f01, #081);
}
.perceptual-mix {
background: linear-gradient(in oklab to right, #f01, #081);
}
The CSS Working Group’s interpolation examples show that sRGB can create a darker midpoint, while Lab or Oklab can produce a more perceptually uniform blend. Polar spaces such as Oklch preserve chroma differently and can take different hue paths. Treat this as a design decision, not a universal upgrade: compare the rendered midpoint, confirm browser support for the syntax, and provide a preceding fallback declaration if necessary.
.banner {
background: linear-gradient(to right, #f01, #081);
background: linear-gradient(in oklab to right, #f01, #081);
}
A browser that rejects the second declaration retains the first.
Write the standards syntax first and let your support policy drive any compatibility transforms. If the project already uses Autoprefixer, it adds or removes vendor prefixes from Can I Use data according to the project’s Browserslist targets; it does not polyfill unsupported gradient behavior. That is why the fallback declaration above still matters for newer syntax.
How do you animate a CSS gradient reliably?
Animating between complete gradient images is not a dependable cross-browser foundation. Animate a property around the gradient instead: move an oversized background, rotate a containing element, cross-fade a pseudo-element, or register a typed custom property used inside the gradient.
The background-position pattern preserves the existing 600% canvas and 12-second timing:
.animated {
background: linear-gradient(270deg, #ee7752, #e73c7e, #23a6d5);
background-size: 600% 600%;
animation: drift 12s ease infinite;
}
@keyframes drift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
Our CSS animations tutorial covers timing and keyframes. Respect reduced-motion preferences when movement is decorative:
@media (prefers-reduced-motion: reduce) {
.animated { animation: none; }
}
For an angle, register the custom property so the browser knows that its values interpolate as angles. The CSS Properties and Values API defines typed custom-property interpolation, and MDN marks the @property at-rule as Baseline 2024.
@property --sweep-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.spinner {
background: conic-gradient(from var(--sweep-angle), #2575fc, #6a11cb);
animation: sweep 2s linear infinite;
}
@keyframes sweep {
to { --sweep-angle: 360deg; }
}
For general theming, ordinary CSS custom properties keep stops in one place:
:root {
--grad-start: #6a11cb;
--grad-end: #2575fc;
}
.card {
background: linear-gradient(135deg, var(--grad-start), var(--grad-end));
}
Which background box does a gradient fill?
The short answer needs two properties. background-origin sets the positioning area and starts at padding-box by default. background-clip sets the painting boundary and starts at border-box, so a background is normally painted underneath a border. The CSS Backgrounds specification defines those defaults separately.
.contained {
border: 8px solid rgb(0 0 0 / 25%);
padding: 24px;
background-image: linear-gradient(to right, #6a11cb, #2575fc);
background-origin: content-box;
background-clip: content-box;
}
This example both positions and clips the gradient to the content box. If a result appears shifted, cropped, or visible under a translucent border, inspect both properties along with background-size, not just background-clip. Our CSS box model guide covers the content, padding, and border boxes behind those values.
What accessibility and rendering checks matter?
- Test contrast everywhere text can land. WCAG 2.2 requires at least 4.5:1 for normal text and 3:1 for large text. With a gradient, test the lowest-contrast point behind each line, not an average color. The exact thresholds are in Success Criterion 1.4.3.
- Do not encode meaning only by color. Add text, icons, patterns, or labels when stops distinguish status or data.
- Offer a motion-reduced state. A static gradient is harmless; an endlessly drifting or rotating one is motion.
- Expect banding. Long, subtle blends can reveal bands on 8-bit displays. An intermediate stop may redistribute the blend, but it cannot guarantee that every display or screenshot pipeline will avoid banding.
- Measure animated effects. A generated gradient avoids an image download, but large animated backgrounds still require repainting. Profile the actual page instead of assuming that “no request” means “no rendering cost.”
For debugging, reduce a failing declaration to two named colors, remove layers, and restore one argument at a time. Check commas first, then direction or shape syntax, stop order, unsupported interpolation syntax, and finally the background sizing and box properties. That sequence usually separates a parsing error from geometry that is valid but visually surprising.