The short version
- CSS cannot put a gradient in border-color, so a CSS gradient border is always drawn with another technique.
- border-image with a gradient is the shortest method, but it ignores border-radius, so it only suits square corners.
- Two background layers, one clipped to the padding box and one to the border box, give a rounded gradient border as long as the inside is a solid colour.
- The mask technique cuts the middle out of a gradient layer, which gives a rounded gradient border with a transparent inside.
- A rotating conic gradient, driven by a custom property registered with @property, is the usual way to animate a gradient border.
On this page
A CSS gradient border is an outline whose colour blends along its length. The catch is that border-color only takes colours, not images, so there is no single property for it. Instead you draw the gradient somewhere else and show only a thin band of it. There are four reliable ways to do that, and the right one depends on two questions: does the element have rounded corners, and does its inside need to be transparent?
| Method | Rounded corners | Transparent inside | Best for |
|---|---|---|---|
border-image | No | Yes | Square cards, dividers, tables |
| Two backgrounds | Yes | No, needs a solid fill | Most cards and buttons |
| Mask on a pseudo-element | Yes | Yes | Cards over images or gradients |
| Pseudo-element behind | Yes | No | Glows and animated rings |
Method 1: border-image
border-image accepts any image, including a gradient. Set a border width and style, then the gradient, then a slice of 1, which tells the browser to use the whole image as the edge. It is two lines, works everywhere, and keeps the inside of the element untouched.
.panel {
border: 3px solid;
border-image: linear-gradient(135deg, #7c3aed, #22d3ee) 1;
}1 is the slice value; without it the border draws only in the corners.Method 2: two backgrounds with background-clip
Give the element a transparent border, then stack two backgrounds. The top layer is the inner fill, clipped to the padding-box, so it stops at the inside edge of the border. The bottom layer is the gradient, clipped to the border-box, so it extends under the border. Where the fill stops, the gradient shows, and it follows border-radius perfectly.
.card {
border: 2px solid transparent;
border-radius: 16px;
background:
linear-gradient(#0f172a, #0f172a) padding-box,
linear-gradient(135deg, #7c3aed, #22d3ee) border-box;
}This is the method to reach for by default. Its one limit is that the inside must be opaque, since a transparent fill would reveal the gradient across the whole card. For cards sitting on a flat page colour, that is no limit at all: use the page colour as the fill.
Method 3: the mask technique for transparent insides
When the card sits over a photo or another gradient, you need the middle to be see-through. Put the gradient on a pseudo-element that covers the card, give it padding equal to the border width, then mask it with two layers: one covering only the content box and one covering everything. Excluding one from the other leaves just the padding ring visible.
.glass-card {
position: relative;
border-radius: 16px;
}
.glass-card::before {
content: "";
position: absolute;
inset: 0;
padding: 2px; /* border width */
border-radius: inherit;
background: linear-gradient(135deg, #7c3aed, #22d3ee);
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask:
linear-gradient(#000 0 0) content-box exclude,
linear-gradient(#000 0 0);
pointer-events: none;
}mask line covers everything current.pointer-events: none stops the pseudo-element swallowing clicks meant for the card's content. The MDN mask-composite reference explains the compositing keywords. This is the method behind most glassmorphism cards with glowing edges.
Method 4: a pseudo-element behind, for glows and animation
Place a gradient pseudo-element slightly larger than the card, behind its content, and cover the middle with a second pseudo-element holding the card's solid fill. The visible edge is the gradient. Because the gradient lives on its own layer, you can blur a copy of it for a glow, or rotate it.
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.ring {
position: relative;
isolation: isolate;
border-radius: 16px;
}
.ring::before {
content: "";
position: absolute;
inset: -2px;
z-index: -1;
border-radius: 18px;
background: conic-gradient(from var(--angle), #7c3aed, #22d3ee, #f472b6, #7c3aed);
animation: spin 6s linear infinite;
}
/* the card's fill, painted over the middle of the ring */
.ring::after {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
background: #0f172a;
}
@keyframes spin {
to { --angle: 360deg; }
}
@media (prefers-reduced-motion: reduce) {
.ring::before { animation: none; }
}--angle lets the browser interpolate the conic start angle smoothly, and ::after paints the fill over the middle.conic-gradient(from 0deg, #7c3aed, #22d3ee, #f472b6, #7c3aed)The outer radius should equal the inner radius plus the border width, which is why the pseudo-element uses 18px around a 16px card. For more ways to put motion into gradients, see CSS animated gradients.
Design tips for gradient borders
Avoid
- Gradient borders on every card in a grid
- Low-saturation gradients on a 1px line, which read as grey
- A gradient border and a gradient fill on the same element
- Fast spinning rings on content people need to read
Do
- Reserve the gradient edge for one highlighted item, such as a featured plan
- Use 2px or more and saturated stops
- A calm fill with a vivid edge, or the reverse
- Slow rotation, paused for reduced motion
Gradient borders work best as emphasis. The same logic applies to buttons, covered in gradient buttons in CSS.
Questions people ask
How do I make a gradient border in CSS?
The quickest way is border: 3px solid; border-image: linear-gradient(135deg, #7c3aed, #22d3ee) 1;. For rounded corners, use two backgrounds clipped to padding-box and border-box.
Why doesn't border-radius work with border-image?
By specification, a border drawn with border-image is not rounded by border-radius. Use the background-clip or mask method for rounded gradient borders.
How do I make a gradient border with a transparent background?
Use the mask technique: a pseudo-element with the gradient, padding equal to the border width, and a mask that excludes its content box.
How do I animate a gradient border?
Register an angle with @property, use it as the from angle of a conic gradient on a pseudo-element, and animate that property from 0deg to 360deg.
Which gradient border method should I use?
Use two backgrounds for most rounded cards and buttons, border-image for square edges, and the mask technique only when the inside must stay transparent.
Written by Gradiently
The team behind Gradiently, a design tool built around Marks: living gradients that make everything you design look like yours.
See our profile


