A Practical Guide to CSS Gradients: Linear, Radial and Conic
How the three CSS gradient types differ, why your gradients look muddy in the middle, and the syntax details that trip people up — angles, color stops, and hard edges.
CSS gives you three gradient functions. Most people learn linear-gradient and force it to do
everything, which is why so many gradients look either flat or muddy.
Linear: an angle and a line
linear-gradient(90deg, #8b5cf6, #ec4899) interpolates along a line. The angle convention is the
part everyone gets wrong: 0deg points up, and angles increase clockwise. So 90deg is
left-to-right, 180deg is top-to-bottom, and to right is an alias for 90deg.
The default when you omit the angle is 180deg, top to bottom.
Radial: a shape and a size
radial-gradient(circle, #8b5cf6, #ec4899) interpolates outward from a center point. Two knobs
matter more than the rest:
- Shape —
circleorellipse. The default isellipse, which stretches to the element's aspect ratio. If you want a true circle in a wide container, say so explicitly. - Position —
radial-gradient(circle at 30% 20%, ...). Off-center radials read as light sources, which is most of what makes a "glow" effect work.
Conic: an angle sweep
conic-gradient(from 0deg, #8b5cf6, #ec4899) sweeps around the center rather than outward from it.
This is the one to reach for when you need pie charts, color wheels, or angular borders. Note
from sets the starting angle, and here 0deg points up as well.
A conic gradient with hard stops is the cheapest possible pie chart:
conic-gradient(#8b5cf6 0% 40%, #ec4899 40% 100%)
Color stops are percentages of the line, not of the element
Every stop takes an optional position. Omit them and the browser distributes stops evenly. Give two stops the same position and you get a hard edge instead of a blend — this is how stripes, progress bars, and pie slices are built.
Three details worth knowing:
Midpoint hints. linear-gradient(red, 30%, blue) inserts a bare percentage between two colors,
which shifts where the 50/50 mix lands without adding a stop. Useful for correcting a gradient that
transitions too early.
Stops outside 0–100%. Perfectly legal, and a good way to use only part of a transition.
Order is enforced. If a later stop has a smaller position than an earlier one, the browser clamps it. Sort your stops.
Why the middle goes gray
Gradients interpolate in sRGB by default. Two saturated colors on opposite sides of the wheel pass through a desaturated middle — purple to yellow goes through gray, blue to orange goes through mud.
Three fixes, in order of effort:
- Add a mid stop. Insert a third color that keeps saturation up through the middle. Works everywhere, costs nothing.
- Shorten the hue distance. Analogous pairs never go muddy because there is no far side of the wheel to cross.
- Interpolate in a better space. Modern browsers support
linear-gradient(in oklch, ...), which keeps perceived lightness and saturation stable across the transition. Check support before relying on it in production.
Banding and performance
Large gradients across a small color distance produce visible bands, because 8-bit channels do not have enough steps. Adding a subtle noise overlay hides it better than adding more stops.
For performance: gradients on background-image are cheap to paint once and expensive to animate.
Animating background-position or gradient stops forces repaint every frame. If you need motion,
animate transform or opacity on a layer that contains the gradient instead.
Try it
- Gradient Editor — build linear, radial and conic gradients with live preview, drag color stops, and copy the CSS
- Palette Generator — find an analogous pair that will not go muddy
- Color Converter — grab the exact HEX values for your stops
Related reading: Building Color Palettes explains the hue-distance rule behind fix #2.