Gradients are generated images. That’s why they:
background-repeatColor stops define where each color appears along the gradient line (or radius / angle).
background: linear-gradient(90deg, khaki, pink);
Expected output: a smooth khaki → pink transition.
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.
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.background-repeatRepeating gradients are often easier than background-repeat for patterns, because the “tile” is described directly in the gradient function.
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:
background-repeat when you have a real “tile” (e.g. an image URL) and want to repeat that tile.linear-gradient() doesn’t repeat by itself. To repeat, either:repeating-* gradient function (repeats the stop range), orbackground-size + background-repeat.A gradient always interpolates in a specific color space. If you don’t specify one, the default depends on the color syntax you use:
rgb() / hsl()), the default is in srgb.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 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);
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.
Keywords and angles both describe direction, but they solve different problems:
to right) map to fixed angles.to top right) aim at a corner, so the implied angle depends on the element’s aspect ratio./* 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:
to right / to bottom / to bottom right when readability matters.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.background: linear-gradient(to top right, #7c3aed 0 50%, #06b6d4 0);
background: linear-gradient(45deg, #7c3aed 0 50%, #06b6d4 0);
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.
Radial gradients have two levers that strongly affect the shape:
circle or ellipse)farthest-side, or explicit radii like circle 80px)Ellipses can sell “light” and “depth” effects because most lighting isn’t perfectly circular.
An extent keyword controls how big the gradient is (where the 100% stop “lands”), measured from the gradient center:
closest-side / farthest-sideclosest-corner / farthest-corner (default)Use the demo below and click the four side/corner handles to see the size change:
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.
Instead of keywords, you can specify radii directly:
circle <length>ellipse <length> <length>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 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 are ideal for angular patterns: rays, wheels, pie slices.
background: conic-gradient(
from 180deg,
#ef4444,
#f59e0b,
#22c55e,
#06b6d4,
#6366f1,
#ef4444
);
border-radius: 999px;
Expected output: a circular color wheel.
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.
Patterns often work best when the pattern layer is subtle and the base layer sets the mood.
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.
in oklch.