Gradients

Treat gradients as background images—learn stops, hard edges, repeating, and the linear/radial/conic building blocks.

Gradients are generated images. That’s why they:

  • Layer like images
  • Can repeat (with repeating gradient functions)
  • Can be combined into patterns and textures
If the idea “gradients are images” feels new, start with Mental Models.

On this page

Stops and Hard Edges

Color stops define where each color appears along the gradient line (or radius / angle).

Smooth stops (default)

background: linear-gradient(90deg, khaki, pink);

Expected output: a smooth khaki → pink transition.

Hard stops (crisp edges)

You get a hard edge by repeating the same stop position:

background: linear-gradient(
  90deg,
  #111827 0% 50%,
  #f59e0b 0 100%
);

Expected output: left half dark, right half amber, with a crisp vertical split.

A stop position of 0 is valid without units. If a stop position would go backwards, the browser clamps it to the previous stop — that’s why patterns like ... 50%, nextColor 0 ... create a sharp edge.

Repeating Gradients vs background-repeat

Repeating gradients are often easier than background-repeat for patterns, because the “tile” is described directly in the gradient function.

Repeating linear stripes

background: repeating-linear-gradient(
  45deg,
  rgb(255 255 255 / 0.16) 0 8px,
  rgb(255 255 255 / 0) 8px 16px
) #0b1020;

Expected output: diagonal stripes on a dark base.

Rule of thumb:

  • Use repeating gradients when the pattern is naturally described by stops.
  • Use background-repeat when you have a real “tile” (e.g. an image URL) and want to repeat that tile.
A normal linear-gradient() doesn’t repeat by itself. To repeat, either:
  • Use a repeating-* gradient function (repeats the stop range), or
  • Treat the whole gradient as a tile via background-size + background-repeat.

Color interpolation

A gradient always interpolates in a specific color space. If you don’t specify one, the default depends on the color syntax you use:

  • If every stop is a legacy sRGB color (hex, named colors, rgb() / hsl()), the default is in srgb.
  • If any stop uses a modern color function (color(), lab(), oklab(), lch(), oklch()), the default becomes in oklab.

You can always override it explicitly:

  • in srgb (legacy behavior)
  • in oklab (modern default when non-legacy colors appear)
  • in oklch (often more perceptually uniform for lightness/hue changes)

Here’s a “trouble pair” where the midpoint is very different. Notice that writing the same endpoints with color(...) switches the default interpolation to oklab (even though the values are still in an sRGB-family space like srgb-linear).

default (sRGB)
in oklab
default (oklab)
in oklch
/* default interpolation */
background: linear-gradient(to right, #ff00ff, #00ff00);

/* in oklab */
background: linear-gradient(to right in oklab, #ff00ff, #00ff00);

/* default oklab with color func */
background: linear-gradient(to right, color(srgb-linear 1 0 1), #00ff00);

/* perceptual interpolation */
background: linear-gradient(to right in oklch, #ff00ff, #00ff00);
This syntax works for linear-gradient(), radial-gradient(), and conic-gradient() (and their repeating-* variants).

If you don’t see a difference, your browser may not support in oklab / in oklch (or color()) yet.

Linear Gradients

Angles vs directions

Keywords and angles both describe direction, but they solve different problems:

  • Side keywords (like to right) map to fixed angles.
  • Corner keywords (like to top right) aim at a corner, so the implied angle depends on the element’s aspect ratio.
90°
Click the arrows for direction. Drag the handle to set angle.
/* Equivalent on any element */
background: linear-gradient(to right, #7c3aed, #06b6d4);
background: linear-gradient(90deg, #7c3aed, #06b6d4);

/* Corner keywords depend on aspect ratio */
background: linear-gradient(to top right, #7c3aed, #06b6d4);
background: linear-gradient(45deg, #7c3aed, #06b6d4); /* only matches on a square */

Guidelines:

  • Use to right / to bottom / to bottom right when readability matters.
  • Use degrees when you need precise control (especially for patterns).
Directional keywords like to bottom right are most useful when you want to point at a corner. They’re especially handy for non-square elements, so you don’t have to compute a “correct” angle.
to top right
45deg
background: linear-gradient(to top right, #7c3aed 0 50%, #06b6d4 0);
background: linear-gradient(45deg, #7c3aed 0 50%, #06b6d4 0);

A practical fade (vignette-ish)

background:
linear-gradient(to bottom, rgb(0 0 0 / 0), rgb(0 0 0 / 0.55)),
radial-gradient(circle at 30% 30%, rgb(255 255 255 / 0.25), transparent 55%),
#0b1020;

Expected output: a subtle highlight plus a darkening toward the bottom.

Copy and paste it into the editor to view it, hiding the background color will make it easier to see the effect of the linear gradient on the surface.

Radial Gradients

Radial gradients have two levers that strongly affect the shape:

  • The shape (circle or ellipse)
  • The size (a keyword extent like farthest-side, or explicit radii like circle 80px)

Circle vs ellipse

Ellipses can sell “light” and “depth” effects because most lighting isn’t perfectly circular.

Extent keywords (closest/farthest side/corner)

An extent keyword controls how big the gradient is (where the 100% stop “lands”), measured from the gradient center:

  • closest-side / farthest-side
  • closest-corner / farthest-corner (default)

Use the demo below and click the four side/corner handles to see the size change:

30% · 30%
Drag the handle to move the center (percent only).
background: radial-gradient(
  ellipse farthest-side at 30% 30%,
  rgb(255 255 255 / 0.28) 0 60%,
  transparent 61%
) #0b1020;

Expected output: a crisp “disk” whose size changes as you switch extent keywords.

Explicit radii (lengths)

Instead of keywords, you can specify radii directly:

  • circle <length>
  • ellipse <length> <length>
circle 72px
ellipse 160px 90px
background: radial-gradient(
  circle 72px at 30% 30%,
  rgb(255 255 255 / 0.28) 0 60%,
  transparent 61%
) #0b1020;

background: radial-gradient(
  ellipse 160px 90px at 30% 30%,
  rgb(255 255 255 / 0.28) 0 60%,
  transparent 61%
) #0b1020;

Repeating radial gradients (dots and rings)

Repeating radial gradients can create dots/rings quickly:

background:
  repeating-radial-gradient(
    circle at 20px 20px,
    rgb(255 255 255 / 0.18) 0 2px,
    rgb(255 255 255 / 0) 0 12px
  ) #0b1020;

Expected output: a dotted pattern anchored at the top-left.

Conic Gradients

Conic gradients are ideal for angular patterns: rays, wheels, pie slices.

Simple color wheel

50% · 50%
90°
Drag the center or angle handle (percent-only positions).
background: conic-gradient(
  from 180deg,
  #ef4444,
  #f59e0b,
  #22c55e,
  #06b6d4,
  #6366f1,
  #ef4444
);
border-radius: 999px;

Expected output: a circular color wheel.

Repeating conic rays (sunburst base)

background: repeating-conic-gradient(
  from 0deg,
  rgb(255 255 255 / 0.22) 0 10deg,
  rgb(255 255 255 / 0) 0 20deg
) #0b1020;

Expected output: rays around the center.

Practical tips

Use alpha to keep patterns theme-friendly

Patterns often work best when the pattern layer is subtle and the base layer sets the mood.

Watch out for banding

Very smooth gradients on large surfaces can show banding depending on the display and colors. If it matters visually, add a tiny noise overlay: /guide/patterns#noise-overlay.

Recap

  • Hard edges come from repeating stop positions.
  • Repeating gradients are often clearer than repeating a background tile.
  • Linear/radial/conic are the building blocks for most backgrounds and patterns.
  • Extents and explicit radii are the two main controls for radial gradient “shape”.
  • If mid-colors look wrong, try in oklch.

Next