MakeMyPalette
← All posts
8 min read

CSS gradients — linear, radial, and conic explained

A thorough walkthrough of CSS gradient syntax, color stops, hard stops, repeating patterns, and creative techniques like conic checkerboards.

The three gradient functions

CSS has three gradient functions: linear-gradient(), radial-gradient(), and conic-gradient(). Each produces an image — not a color — which is why they’re valid values for background-image (or the background shorthand) but not for color.

All three share the same color-stop syntax, but they differ in how they map those stops to pixels. Understanding the mapping for each type is the key to predicting what your gradient will look like.

Linear gradients

A linear gradient draws color along a straight line called the gradient line. The line’s angle determines the direction of color change.

background: linear-gradient(135deg, #6366f1, #ec4899);

The angle is measured clockwise from the top of the element. 0deg goes bottom-to-top, 90deg goes left-to-right, 180deg goes top-to-bottom (the default when no angle is specified). You can also use keywords: to right, to bottom left, etc.

An important detail: the gradient line extends beyond the element’s corners so that the specified colors always cover the entire box. This means a 45deg gradient on a rectangle is longer than the box’s diagonal. The spec calls this the “ending-point” calculation — it ensures the last color stop always reaches the far corner regardless of aspect ratio.

Color stops and positions

Each color stop can have an explicit position as a percentage or length value:

background: linear-gradient(
  to right,
  #6366f1 0%,
  #8b5cf6 40%,
  #ec4899 100%
);

When you omit positions, the browser distributes stops evenly. Two stops = 0% and 100%. Three stops = 0%, 50%, 100%. Explicit positions let you compress or expand specific color transitions — pushing a midpoint to 40% makes the purple-to-pink transition wider than the indigo-to-purple one.

You can also give a stop two positions to create a hard edge:

background: linear-gradient(
  to right,
  #6366f1 0%,
  #6366f1 50%,
  #ec4899 50%,
  #ec4899 100%
);

This produces a sharp split at 50% — no transition at all. The shorthand for this is a single stop with two positions: #6366f1 0% 50%, #ec4899 50% 100%. Hard stops are the basis of striped patterns, progress bars, and flag-style backgrounds.

Radial gradients

A radial gradient draws color outward from a center point in an elliptical (or circular) shape.

background: radial-gradient(circle at center, #6366f1, #0a0a0a);

The shape keyword (circle or ellipse) controls the aspect ratio. Omitting it defaults to ellipse, which stretches to match the element’s bounding box. The at keyword sets the center point — at center, at top left, at 30% 60%, or any valid position.

The size keyword controls how far the gradient extends:

  • closest-side — the gradient edge touches the nearest side
  • farthest-side — the gradient edge touches the farthest side
  • closest-corner — the gradient edge touches the nearest corner
  • farthest-corner (default) — the gradient edge reaches the farthest corner

The difference matters most when the center is off-center. A spotlight effect on a hero section might use circle at 30% 40% with closest-side to keep the glow tight, while a full-bleed background uses the default farthest-corner to ensure coverage.

Conic gradients

A conic gradient sweeps color around a center point like a pie chart. Color transitions happen along the angle axis rather than along a line or radius.

background: conic-gradient(from 0deg, #f87171, #facc15, #4ade80, #38bdf8, #818cf8, #f87171);

That example creates a color wheel: it starts at red (0°), rotates through yellow, green, cyan, purple, and wraps back to red. The from keyword sets the starting angle. The at keyword sets the center, same as radial gradients.

Conic gradients make pie-chart-style visuals trivial. A two-segment pie (70% / 30%) is:

background: conic-gradient(#6366f1 0% 70%, #e5e5e5 70% 100%);

No JavaScript, no SVG, no canvas — one CSS property. Combined with border-radius: 50%, you get a clean donut or pie chart.

Repeating gradients

Each gradient function has a repeating variant: repeating-linear-gradient(), repeating-radial-gradient(), and repeating-conic-gradient(). The color stops tile instead of stretching to fill the element.

background: repeating-linear-gradient(
  45deg,
  #6366f1 0px,
  #6366f1 10px,
  #818cf8 10px,
  #818cf8 20px
);

This produces diagonal stripes 10px wide — indigo and lighter indigo alternating forever. The stop positions define one “tile” of the pattern, and the browser repeats it until the element is covered.

A checkerboard using conic gradients is a classic trick:

background: repeating-conic-gradient(
  #e5e5e5 0% 25%,
  #ffffff 0% 50%
) 0 0 / 40px 40px;

Each 25% arc alternates between gray and white, and the background-size: 40px 40px tiles it. The result is a checkerboard pattern in two lines of CSS. This is the same pattern used behind transparent regions in image editors.

Color interpolation and color spaces

By default, CSS gradients interpolate in the sRGB color space. This works fine for most cases but produces muddy midpoints for certain hue combinations — a gradient from blue to yellow passes through a desaturated gray-green in sRGB.

Modern CSS lets you choose the interpolation color space:

background: linear-gradient(in oklch, #6366f1, #facc15);

Using oklch or oklab keeps the midpoints perceptually vibrant. The gradient from blue to yellow in oklch passes through vivid greens instead of mud. Browser support for in <color-space> landed in Chrome 111, Safari 16.2, and Firefox 127.

You can also control the hue interpolation direction in cylindrical spaces (oklch, hsl, hwb):

background: linear-gradient(in oklch longer hue, red, red);

That creates a full rainbow by taking the “longer” hue path around the wheel from red back to red — covering all 360° of hue.

Performance notes

Gradients are rasterized by the browser’s compositor and are generally cheap to render. They don’t trigger layout or paint in the expensive sense — resizing the element re-rasterizes the gradient, but it’s GPU-friendly work.

Animating gradient properties (like stop positions or angles) is a different story. CSS gradients can’t be natively interpolated between keyframes — the browser re-paints the entire gradient image on each frame. If you need a smoothly animated gradient, consider using CSS @property to register custom properties for the color stops, then animate those registered properties. This lets the browser interpolate the values without re-painting the entire gradient from scratch:

@property --stop-1 {
  syntax: '<color>';
  initial-value: #6366f1;
  inherits: false;
}

.animated-gradient {
  background: linear-gradient(var(--stop-1), var(--stop-2));
  transition: --stop-1 0.3s, --stop-2 0.3s;
}

Build your gradient

If you want to experiment with all three gradient types interactively — with live preview and one-click CSS copy — try the Gradient Generator. It supports linear, radial, and conic types with multi-stop controls and angle adjustment.

Ready to put this into practice?

Open the tool →