In this tutorial, we’ll focus on CSS linear gradients and the most common things users want to do with them: backgrounds, multiple colors, opacity, borders, animation, and text.

Let’s go through everything step by step, with playgrounds you can click and edit as you go.

What Is a CSS Gradient?

A CSS gradient is a special kind of image generated by the browser. That’s why you usually apply it to properties that accept images, like background or background-image.

  • Gradients are not colors (even though they look like colorful backgrounds).
  • They behave like images: you can position them, size them, repeat them, layer them, etc.
  • You can stack multiple backgrounds (including multiple gradients) using commas.

CSS Linear Gradient Background and Syntax

The core function is linear-gradient(). The simplest version looks like this:

background: linear-gradient(color1, color2);

If you don’t specify a direction, the default is top → bottom (meaning the first color starts at the top).

.demo {
  background: linear-gradient(#ffdd55, #ff4d6d);
}
  
.demo {
  background: linear-gradient(to right, #ffdd55, #ff4d6d);
}
  
.demo {
  background: linear-gradient(135deg, #ffdd55, #ff4d6d);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
}

.demo {
  height: 220px;
  border: 3px solid #111;
  border-radius: 16px;
  display: grid;
  place-items: center;
  background: #f2f2f2;
  color: #111;
  font-weight: 700;
  font-size: 18px;
}

.note {
  margin-top: 12px;
  font-size: 14px;
  opacity: 0.85;
  line-height: 1.45;
}
  
Linear Gradient

Try the snippets: default (top to bottom), to right, and 135deg. Gradients are images, so you apply them to background or background-image.

Direction Cheat Sheet

  • to right means left → right
  • to left means right → left
  • to bottom means top → bottom (the default)
  • to top means bottom → top

Angles are also allowed, like 45deg. Think of it as rotating the gradient line.

CSS Linear Gradient Multiple Colors

You can add as many color stops as you want. Each comma-separated value becomes a stop.

When you add percentages, you control where each color “lands” along the gradient.

.demo {
  background: linear-gradient(to right, #00c2ff, #7cffcb, #fff38a);
}
  
.demo {
  background: linear-gradient(
    to right,
    #00c2ff 0%,
    #7cffcb 45%,
    #fff38a 100%
  );
}
  
.demo {
  background: linear-gradient(
    to right,
    #00c2ff 0%,
    #00c2ff 33%,
    #7cffcb 33%,
    #7cffcb 66%,
    #fff38a 66%,
    #fff38a 100%
  );
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
}

.demo {
  height: 220px;
  border: 3px solid #111;
  border-radius: 16px;
  display: grid;
  place-items: center;
  color: #111;
  font-weight: 800;
  letter-spacing: 0.3px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.55);
}

.note {
  margin-top: 12px;
  font-size: 14px;
  opacity: 0.85;
  line-height: 1.45;
}
  
Multiple Stops

Snippet 1 is a smooth blend. Snippet 2 adds “landing points” (percentages). Snippet 3 shows hard stops (by repeating the same color at multiple positions).

Quick Trick: Hard Stops

If you want sharp bands instead of blending, repeat the same color at the boundary:

  • #00c2ff 33% then #7cffcb 33% makes a crisp edge.

CSS Linear Gradient With Opacity

Opacity is usually done with rgba() or hsla(). This is super useful when you want a gradient overlay on top of an image, or when you want the background behind the element to show through.

.overlay {
  background: linear-gradient(
    to right,
    rgba(0, 0, 0, 0.70),
    rgba(0, 0, 0, 0.00)
  );
}
  
.overlay {
  background: linear-gradient(
    135deg,
    rgba(255, 0, 90, 0.55),
    rgba(0, 180, 255, 0.35),
    rgba(255, 230, 120, 0.25)
  );
}
  
.overlay {
  background:
    linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.65),
      rgba(0, 0, 0, 0.10)
    ),
    url("https://picsum.photos/970/410");
  background-size: cover;
  background-position: center;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
}

.card {
  border: 3px solid #111;
  border-radius: 18px;
  overflow: hidden;
}

.overlay {
  min-height: 260px;
  display: grid;
  align-content: end;
  padding: 18px;
  color: #fff;
}

.overlay h3 {
  margin: 0;
  font-size: 22px;
  line-height: 1.15;
}

.overlay p {
  margin: 10px 0 0;
  max-width: 60ch;
  font-size: 14px;
  opacity: 0.92;
  line-height: 1.45;
}
  

Opacity Gradients

Snippet 1 is a classic “fade to transparent”. Snippet 2 uses multiple translucent colors. Snippet 3 stacks a gradient on top of an image.

Opacity Tip

If you want opacity for the background only, don’t use opacity: 0.5; on the element. That fades everything (including text). Use rgba() in your gradient instead.

CSS Linear Gradient Border

You can’t directly do border-color: linear-gradient(...), because borders expect a color, not an image.

But you can fake a gradient border by layering two backgrounds:

  • One background for the inside (usually solid)
  • One background for the border area (the gradient)

This is one of those “CSS magician” tricks that feels illegal, but it’s actually very reliable once you understand it.

.card {
  border: 10px solid transparent;
  background:
    linear-gradient(#ffffff, #ffffff) padding-box,
    linear-gradient(135deg, #00c2ff, #7cffcb, #fff38a) border-box;
}
  
.card {
  border: 10px solid transparent;
  background:
    linear-gradient(#ffffff, #ffffff) padding-box,
    linear-gradient(to right, #ff4d6d, #8a2be2) border-box;
}
  
.card {
  border: 10px solid transparent;
  background:
    linear-gradient(#ffffff, #ffffff) padding-box,
    linear-gradient(
      to right,
      #00c2ff 0%,
      #00c2ff 33%,
      #7cffcb 33%,
      #7cffcb 66%,
      #fff38a 66%,
      #fff38a 100%
    ) border-box;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
}

.card {
  border-radius: 18px;
  padding: 16px;
  color: #111;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12);
}

.card h3 {
  margin: 0;
  font-size: 20px;
}

.card p {
  margin: 10px 0 0;
  max-width: 68ch;
  font-size: 14px;
  line-height: 1.5;
  opacity: 0.9;
}

.hint {
  margin-top: 12px;
  font-size: 13px;
  opacity: 0.85;
}
  

Gradient Border (No Images)

This border is a gradient because we draw two backgrounds: a white one clipped to the padding box, and a gradient one clipped to the border box.

Try each snippet to swap the gradient style.

Why This Works

  • border: 10px solid transparent; creates border space.
  • The first background is clipped to padding-box (so it fills the inside only).
  • The second background is clipped to border-box (so it covers border + inside).
  • The inside stays white because it’s painted on top (first layer).

CSS Linear Gradient Transition (Animated)

Two common beginner questions:

  1. “Can I transition a gradient?”
  2. “How do I animate one?”

You can animate gradients, but the smoothest and most reliable approach is often to animate something around the gradient, like:

  • background-position
  • background-size
  • or swap between gradients on hover (sometimes it snaps depending on the browser)

Here’s a clean “moving gradient” pattern using background-size and background-position:

.button {
  background: linear-gradient(90deg, #ff4d6d, #8a2be2, #00c2ff);
  background-size: 220% 220%;
  background-position: 0% 50%;
  transition: background-position 600ms ease;
}

.button:hover {
background-position: 100% 50%;
} 
.button {
  background: linear-gradient(90deg, #ff4d6d, #8a2be2, #00c2ff);
  background-size: 300% 300%;
  animation: gradient-slide 2.2s ease infinite;
}

@keyframes gradient-slide {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
  
.button {
  background: linear-gradient(135deg, #111111, #111111);
  transition: background 400ms ease;
}

.button:hover {
  background: linear-gradient(135deg, #ffdd55, #ff4d6d);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
}

.button {
  border: 3px solid #111;
  border-radius: 999px;
  padding: 14px 18px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: #fff;
  font-weight: 800;
  letter-spacing: 0.2px;
  text-decoration: none;
  user-select: none;
  cursor: pointer;
}

.row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.note {
  margin-top: 12px;
  font-size: 14px;
  opacity: 0.9;
  line-height: 1.45;
  max-width: 74ch;
}
  

Snippet 1 animates a gradient on hover by moving background-position. Snippet 2 runs a continuous animation with @keyframes. Snippet 3 swaps gradients on hover (this might look snappy in most browsers).

A Realistic Expectation for “Gradient Transitions”

If you try to transition from one gradient to a different gradient, most browsers won’t interpolate it smoothly. If you want “always smooth”, animate background-position (or use layered gradients and fade the layer with opacity on a pseudo-element).

CSS Linear Gradient Text

Gradient text is another great trick. The idea is simple:

  • Put the gradient on the element’s background.
  • Clip the background to the text shapes.
  • Make the text fill transparent so the background shows through.
.title {
  background: linear-gradient(90deg, #ff4d6d, #8a2be2, #00c2ff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
  
.title {
  background: linear-gradient(
    135deg,
    #00c2ff 0%,
    #7cffcb 45%,
    #fff38a 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
  
.title {
  background: linear-gradient(90deg, #ff4d6d, #8a2be2, #00c2ff);
  background-size: 300% 300%;
  background-position: 0% 50%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: title-shift 8.4s ease infinite;
}

@keyframes title-shift {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  max-width: 980px;
  padding: 18px;
  font-family: system-ui, Arial, sans-serif;
}

.title {
  margin: 0;
  font-size: clamp(34px, 5vw, 68px);
  font-weight: 900;
  letter-spacing: -0.02em;
  line-height: 1.02;
}

.sub {
  margin: 10px 0 0;
  font-size: 14px;
  opacity: 0.9;
  line-height: 1.45;
  max-width: 70ch;
}

.panel {
  border: 3px solid #111;
  border-radius: 18px;
  padding: 18px;
  background: #ffffff;
}
  

Gradient Text

The gradient is on the background, then clipped to the letters. Snippet 3 animates the gradient for a “shimmer” effect.

Why Those -webkit- Lines?

-webkit-background-clip: text; and -webkit-text-fill-color: transparent; are still needed for reliable gradient text support in browsers based on WebKit/Blink. Keeping both the standard and WebKit lines is a common, practical pattern.

Common Problems and Fixes

My gradient doesn’t show up

  • Make sure the element has size. For example, a div with no content might collapse to height 0.
  • Make sure you’re using background or background-image, not something like color.
  • If you’re layering backgrounds, remember commas create layers, and the first layer is on top.

My “gradient border” fills the whole box

  • You probably forgot the white padding-box layer, or the border isn’t transparent.
  • Use the exact pattern:
    • border: Npx solid transparent;
    • background: linear-gradient(white, white) padding-box, linear-gradient(...) border-box;

My gradient transition looks jumpy

  • Try animating background-position instead of transitioning between two different gradients.
  • Or animate a pseudo-element’s opacity (fade between layers).

CSS Linear Gradient Conclusion

You now have the “big six” linear gradient skills:

  • Syntax and direction/angles
  • Multiple colors and color stops (including hard edges)
  • Opacity with rgba() and stacked overlays
  • Gradient borders using layered backgrounds
  • Animated gradients using background-position and @keyframes
  • Gradient text with -webkit-background-clip: text and background-clip: text

Further Reading

Learn more about CSS gradients in the CSS Gradient Interactive Tutorial, and learn more specifically about radial-gradient() in the CSS Radial Gradient Interactive Tutorial.