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 GradientTry the snippets: default (top to bottom), to right, and 135deg. Gradients are images, so you apply them to
backgroundorbackground-image.
Direction Cheat Sheet
to rightmeans left → rightto leftmeans right → leftto bottommeans top → bottom (the default)to topmeans 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 StopsSnippet 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 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:
- “Can I transition a gradient?”
- “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-positionbackground-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
divwith no content might collapse to height 0. - Make sure you’re using
backgroundorbackground-image, not something likecolor. - 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-boxlayer, 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-positioninstead 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-positionand@keyframes - Gradient text with
-webkit-background-clip: textandbackground-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.
