CSS Gradients: Linear, Radial and Conic, Without the Muddy Middle
How to write linear, radial and conic CSS gradients, use color stops and hard stops, avoid gray dead zones, and keep text on a gradient readable.
By ColorOverflow Editorial TeamUpdated November 13, 20266 min readIntermediate
A CSS gradient is an image the browser draws from a list of colors. You can use one anywhere an image goes, most often as a background-image, and it scales to any size without blurring. CSS has three kinds: linear, radial and conic, plus repeating versions of each.
This guide covers the syntax, then the two things that trip people up most: gradients that turn gray and muddy in the middle, and text that's readable at one end of a gradient but not the other.
Linear gradients
linear-gradient() blends colors along a straight line. The first value is the direction, as an angle such as 90deg (left to right) or a keyword such as to bottom right. Without a direction the gradient runs from top to bottom.
Indigo to pink, left to right. Two colors close enough on the wheel blend cleanly in any color space.
CSS
background-image: linear-gradient(90deg, #4f46e5, #db2777);Color stops and positions
Each color is a color stop. With no positions, stops are spread evenly. Add a length or percentage after a color to place it exactly, and add a bare percentage between two stops to move the point where they meet halfway. That bare value is called an interpolation hint.
Three analogous colors from the Palette Generator, with the middle stop pushed to 60%.
CSS
background-image: linear-gradient(90deg, #63adf1, #6366f1 60%, #a763f1);Hard stops
When two stops share the same position, the color changes instantly instead of blending. A stop can also take two positions, which sets where a solid band starts and ends. That's how you draw stripes, flags and progress bars without any images.
Three solid bands. Each color's end position equals the next color's start, so there's no blending.
CSS
background-image: linear-gradient(90deg, #4f46e5 0 33%, #f59e0b 33% 66%, #14b8a6 66%);Radial gradients
radial-gradient() spreads colors outward from a point, as a circle or an ellipse. You can set the shape, the size and the center, such as circle at 30% 30%. Radial gradients work well for soft glows, spotlights and a subtle vignette behind a hero image.
A warm glow, centered up and to the left, fading from yellow through orange to a deep rust.
CSS
background-image: radial-gradient(circle at 30% 30%, #fde047, #f97316 55%, #9a3412);Conic gradients
conic-gradient() sweeps colors around a center point, like the hands of a clock. With hard stops it draws a pie chart; with smooth stops through the hues it draws a color wheel.
A pie of 40%, 30% and 30%, drawn with hard stops. Wrap it in a circle with border-radius: 50%.
CSS
background-image: conic-gradient(#4f46e5 0 40%, #f59e0b 40% 70%, #14b8a6 70%);A hue wheel. Repeating the first color at the end closes the circle without a seam.
CSS
background-image: conic-gradient(#ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);Repeating gradients
repeating-linear-gradient(), repeating-radial-gradient() and repeating-conic-gradient() tile their stops over and over. Combined with hard stops, they make stripes and patterns from a single line of CSS.
Diagonal stripes, 12px each, for a subtle placeholder or a disabled area.
CSS
background-image: repeating-linear-gradient(45deg, #f3f4f6 0 12px, #e0e7ff 12px 24px);Avoiding the gray dead zone
By default, browsers blend gradient colors in sRGB, averaging the red, green and blue values. When the two ends sit far apart on the color wheel, that average lands near gray. Blue #2563EB to amber #F59E0B passes through #8D817B at the midpoint, which is hsl(20, 7%, 52%): almost no color at all.
The default blend. Look at the middle: the two vivid colors meet in a dull brownish gray.
CSS
background-image: linear-gradient(90deg, #2563eb, #f59e0b);Fix 1: interpolate in OKLCH
Modern CSS lets you choose the color space a gradient blends in. Writing in oklch keeps lightness and chroma steady and travels around the hue wheel instead of through the gray center. As of November 2026, gradient interpolation color spaces are Baseline, supported in every major browser since June 2024.
The same two colors blended in OKLCH. The shorter way around the wheel from blue to amber passes through violet and pink, so the middle stays colorful.
CSS
background-image: linear-gradient(in oklch 90deg, #2563eb, #f59e0b);You can also write in oklab, which keeps lightness even but still moves in a straight line, so very different hues can lose some color in the middle. For older browsers, declare a plain gradient first and the in oklch version second; a browser that doesn't understand the second keeps the first.
Fix 2: add a midpoint stop
The approach that works everywhere is to add the middle color yourself. The OKLCH halfway point between this blue and amber is a pink close to #DF57A9. With it as a third stop, each half of the gradient blends between neighbors, and neither half goes gray.
A hand-picked pink midpoint, #DF57A9. Plain sRGB blending, no gray.
CSS
background-image: linear-gradient(90deg, #2563eb, #df57a9, #f59e0b);Building gradients from a palette
The easiest gradients to get right use colors that are already close on the color wheel. An analogous palette from the Palette Generator gives you three to five neighboring hues that blend smoothly in any color space. A monochromatic palette gives a gentle light-to-dark fade.
- Pick two or three neighboring colors for smooth backgrounds; more stops quickly look busy.
- For complementary or triadic palettes, add a midpoint stop or use in oklch, or the middle will dull.
- Keep the lightness of the stops close if text will sit on top, so contrast doesn't swing across the gradient.
- Reuse your palette's exact values so gradients match the rest of the interface.
Text on gradients
Text on a gradient sits on many background colors at once, so check it against every stop and against the midpoints between them. The weakest point sets the real contrast.
White text on the indigo to pink gradient above passes all the way across. Against indigo #4F46E5 it gets 6.28:1, against the pink #DB2777 4.59:1, and against the sRGB midpoint #9537AE 6.11:1. The lowest is 4.59:1, so normal text meets the 4.5:1 minimum.
The analogous gradient is a different story. White text gets only 2.39:1 on the light blue #63ADF1 and 4.46:1 on the indigo #6366F1. Near-black #111827 does better at the light end, 7.41:1, but only 3.97:1 on the indigo and 4.81:1 on the violet #A763F1. Neither color passes across the whole gradient.
- Darken or lighten the whole gradient so one text color passes everywhere.
- Keep text over the part of the gradient where it passes, and check that part at every screen width.
- Put a solid or semi-transparent panel behind the text, and check the blended panel color.
- Use the 3:1 large-text minimum only for genuinely large text, not as a shortcut.
Quick reference
- linear-gradient(direction, stops): along a line, such as 90deg or to right.
- radial-gradient(shape at position, stops): outward from a point.
- conic-gradient(from angle at position, stops): around a point.
- Hard stop: give two colors the same position, such as #4f46e5 50%, #f59e0b 50%.
- Repeating: the same functions with a repeating- prefix tile their stops.
- No gray middle: add a midpoint stop, or add in oklch before the direction.
A good gradient is a palette in motion. Start from colors that already work together, give distant hues a helping stop, and check text where the background is weakest.
Color Wheel ExplorerDrag a color around the wheel and watch each harmony rule update.