# Understanding gradients

> A deep dive into how gradients work, how color models affect them and why some gradients look better than others.
>
> Source: https://jakub.kr/work/gradients. Interactive demos are only available on the page.

A deep dive into how gradients work, how color models affect them and why some gradients look better than others.

## What is a gradient?

We use gradients every day and they might seem fairly straightforward but they hide a surprising amount of complexity and let you do some very interesting things.

A gradient is a smooth transition between two or more colors. In CSS, gradients are defined by color stops. These are points that mark where each color starts and ends. The colors are mathematically blended, which is referred to as interpolation.

## Gradient types

There are three primary gradient types: `linear`, `radial` and `conic`.

## Linear gradients

Linear gradients are the most common type. They are pretty straightforward as they blend colors along a straight line.

By default, the gradient goes from `top` to `bottom`, but you can control the direction, color stops and even repetition.

```css title="linear-gradient.css"
element {
  background: linear-gradient(to bottom, blue, red);
}
```

### Direction and angle

You can define the direction of the gradient by using either a keyword or a degree value and the angles rotate clockwise.

The keywords include `top`, `left`, `right` and `bottom`. You can also combine these and do something like `to bottom right`.

```css title="linear-gradient-angle.css"
element {
  background: linear-gradient(45deg, blue, red);
}
```

### Color stops

You can define individual color stops that let you control exactly where colors start and stop.

```css title="color-stops.css"
element {
  background: linear-gradient(to bottom, blue 25%, red 75%);
}
```

If you place two color stops at the same position, they create a sharp edge.

```css title="hard-stop-gradient.css"
element {
  background: linear-gradient(to bottom, blue 50%, red 50%);
}
```

### Repeating linear gradients

You can also use the `repeating` type to have the gradient repeat. This is particularly useful if you want to create a pattern or a texture.

```css title="repeating-linear-gradient.css"
element {
  background: repeating-linear-gradient(45deg, blue 0 10px, red 24px 20px);
}
```

### Diamond gradient

Some design tools like Figma also include a diamond gradient, which radiates outward in a square shape.

This effect is done by layering four linear gradients, each positioned at a corner and sized to cover a quarter of the element. Diamond is not a gradient type in CSS.

```css title="diamond-gradient.css"
element {
  background:
    linear-gradient(to bottom right, #fff 0%, #999 50%) bottom right / 50% 50%
      no-repeat,
    linear-gradient(to bottom left, #fff 0%, #999 50%) bottom left / 50% 50%
      no-repeat,
    linear-gradient(to top left, #fff 0%, #999 50%) top left / 50% 50% no-repeat,
    linear-gradient(to top right, #fff 0%, #999 50%) top right / 50% 50%
      no-repeat;
}
```

## Radial gradients

Radial gradients radiate outward from a center point. They are great for glows, backgrounds or depth lighting.

```css title="radial-gradient.css"
element {
  background: radial-gradient(blue, red);
}
```

### Shapes

In radial gradients you can define one of two shapes: a `circle` or an `ellipse`. The difference is that `circle` always maintains a `1:1` aspect ratio, while `ellipse` stretches with the container.

If you don't define the shape, the gradient will automatically default to `ellipse`.

```css title="radial-shape.css"
element {
  background: radial-gradient(circle, blue, red);
}
```

### Size keywords

You can also control how far the gradient extends. The available values here are `closest-side`, `closest-corner`, `farthest-side` and `farthest-corner`.

This determines how far it extends from its center point before it reaches the final color stop. If you don't define the size keyword, the gradient will default to `farthest-corner`.

```css title="radial-size.css"
element {
  background: radial-gradient(circle closest-side, blue, red);
}
```

### Position

Another thing that you have control over in radial gradients is the position. You can move the center of the gradient to a different position.

The default value is `center`, but it accepts keywords, percentages or coordinates.

```css title="radial-position.css"
element {
  background: radial-gradient(circle at 70% 30%, blue, red);
}
```

## Conic gradients

Conic gradients are the newest gradient type in CSS. They rotate around a central point, similar to slices of a color wheel.

They are great for charts, rings, animated borders or more complex visual effects.

```css title="conic-gradient.css"
element {
  background: conic-gradient(blue, red);
}
```

### Starting angle

Similar to the other gradient types, you can customize the starting angle. In conic gradients the color stops are placed along angles and they are defined in degrees.

If you don't define it, it defaults to `0deg`. The gradient also automatically wraps back to the first color stop.

```css title="conic-start-angle.css"
element {
  background: conic-gradient(from 90deg, blue, red);
}
```

### Center position

You can move the rotation center with an `at` value.

Without defining the value, it defaults to `at 50% 50%`.

```css title="conic-position.css"
element {
  background: conic-gradient(at 70% 30%, blue, red);
}
```

### Hard edges

Similar to `linear` gradients, you can also make the gradient look like it has sharp edges.

```css title="conic-hard-edges.css"
element {
  background: conic-gradient(
    purple 0deg 120deg,
    red 120deg 240deg,
    blue 240deg 360deg
  );
}
```

### Repeating conic gradients

You can also repeat `conic` gradients to create patterns.

Tweaking the `deg` values and the number of repetitions and gradients allows you to create unique patterns.

```css title="repeating-conic-gradient.css"
element {
  background: repeating-conic-gradient(
    from 0deg,
    #000 0deg 20deg,
    #fff 20deg 40deg
  );
}
```

## Gradients and color spaces

All of the examples above have used the `sRGB` color space, which is the default on the web. Gradients behave differently depending on the color space used, though.

If you want to learn more about color spaces, I recommend reading the [article](/components/oklch-colors) about OKLCH colors.

To use newer color models for gradients, you can add the color space directly in the gradient definition.

```css title="oklch-gradient.css"
element {
  background: linear-gradient(in oklch, blue, red);
}
```

In Tailwind, you can force the color space by adding the `color-space` utility. Tailwind 4 defaults to `oklab` for gradients.

```tsx title="tailwind-color-space.tsx"
<div class="bg-linear-to-r/oklch from-red-500 to-blue-500" />
```

As mentioned earlier, gradients are just mathematical blends of colors. The way these colors blend depends on two things: the type of gradient and the color space used.

To explain this simply, `rgb` interpolates colors in a straight line but only allows you to use `sRGB` colors. `oklab` also interpolates colors in a straight line but it allows you to use `Display-P3` colors.

`oklch` doesn't interpolate in a straight line, but instead in a circle, because in `oklch` hue is angular. It also allows you to use `Display-P3` colors.

In the example above, you can see that the `oklch` gradients look different compared to `rgb` and `oklab`. This is due to the difference in interpolation.

This can be a double-edged sword. While some gradients look smoother and more vibrant, you might also see colors that you've never defined.

## Color hints

Modern CSS also supports color hints, which let you control where the midpoint between colors appears. This is different from setting stop positions.

Color stops define where a color starts and ends, while hints only define where the color blend appears on the gradient.

```css title="color-stops-with-hint.css"
element {
  background: linear-gradient(to right, red 0%, blue 100%);
}
```

For example, in this gradient red is locked at `0%` and blue is locked at `100%`. The browser linearly interpolates between these two positions.

```css title="color-stop-midpoint.css"
element {
  background: linear-gradient(to right, red 0%, green 50%, blue 100%);
}
```

If you add a midpoint, red lives up to `50%`, green starts and ends at `50%` and acts as a stop and then the gradient interpolates from green to blue.

```css title="color-hint.css"
element {
  background: linear-gradient(to right, red, 40%, blue);
}
```

Color hints don't define new colors. They control where the *transition* between two colors appears between stops. They change the rate of interpolation, not the endpoints.

The marker shows where the midpoint appears. With a `30%` hint, red transitions faster and blue takes up more space. With `70%`, red dominates longer before transitioning.

You can also use multiple hints in a single gradient to have full control over where the color interpolation happens.

## Gradient layering

Layering gradients on top of one another allows you to create unique effects. This, in combination with `background-blend-mode`, unlocks the real magic of gradients.

Combining different blend modes together can create even more interesting effects.

```css title="layered-gradient.css"
.layered-gradient {
  background:
    linear-gradient(
      in oklch 135deg,
      oklch(0.75 0.18 280),
      oklch(0.8 0.15 80),
      oklch(0.75 0.18 320)
    ),
    conic-gradient(
      in oklch from 180deg,
      oklch(0.7 0.12 200 / 0.3),
      oklch(0.7 0.12 340 / 0.3),
      oklch(0.7 0.12 200 / 0.3)
    );
  background-blend-mode: overlay, color-dodge;
}
```

## Performance

Gradients are GPU-accelerated in modern browsers. This means properties like position, angle or size can be animated very efficiently as long as the gradient itself isn't being recalculated.

For example, an animated `conic` gradient can be used as a passkey-style progress indicator.
