In this guide
What you will learn
- Technique 1: The border-image Gradient
- Technique 2: The padding-box and border-box Double Background
- Technique 3: A Masked Pseudo-Element for Transparent Centers
- Which Gradient Border Technique Should You Use?
There is no border-color: linear-gradient() in CSS, so every CSS gradient border is a workaround, and the most obvious one breaks as soon as you add border-radius. This guide walks through three techniques, explains exactly why border-image ignores rounded corners, and shows which approach to use when you need a solid fill, a transparent center or an animated border.
Technique 1: The border-image Gradient
The most direct way to paint a gradient on a border is border-image, which accepts a gradient as its source image:
.box {
border: 4px solid;
border-image: linear-gradient(135deg, #14b8a6, #8b5cf6) 1;
}
The 1 at the end is border-image-slice, and it is not optional. The default slice is 100%, which assigns the entire gradient to the four corners and leaves the edges empty, so without it you see colored corners and no sides. A slice of 1 cuts a thin strip from each edge of the image and stretches it along the matching side, which for a gradient produces a continuous border.
A border style is still required. Here solid in the shorthand provides it; with no style, the border width computes to zero and nothing is drawn.
Why border-image ignores border-radius
Add border-radius: 16px to the example above and the corners stay square. This is not a browser bug: the specification says an element's backgrounds are clipped to the rounded curve, but its border image is not. The result can look worse than a plain square box, because the background is rounded while the border image is not, leaving small mismatched slivers inside the corners.
That makes border-image the right choice only in specific cases:
- Square-cornered elements such as table cells, dividers and full-bleed sections.
- Single-side accents, such as a gradient rule under a heading or along the left edge of a callout. Give only that side a border, for example
border-left: 4px solid, and the sameborder-imageline paints just that side. - Elements whose background you do not control, because
border-imagedoes not depend on it.
Technique 2: The padding-box and border-box Double Background
This is the most practical way to get a gradient border radius that actually curves. Instead of painting the border, you paint two background layers and let a transparent border reveal one of them:
.card {
border: 3px solid transparent;
border-radius: 16px;
background:
linear-gradient(#ffffff, #ffffff) padding-box,
linear-gradient(135deg, #14b8a6, #8b5cf6) border-box;
}
How it works:
- The border is transparent, so whatever background sits beneath it shows through.
- The second layer, the gradient, uses
border-box, so it fills the entire element including the border area. - The first layer is painted on top and uses
padding-box, so it covers everything except the border, leaving only a gradient ring visible. - Both layers are clipped by
border-radius, so the ring curves correctly and the inner corner radius automatically shrinks by the border width.
Two details trip people up. First, the inner fill is written as linear-gradient(#ffffff, #ffffff) instead of a plain color. background-color is always painted beneath every layer and clipped like the bottom layer, so it cannot be restricted to the padding box while the gradient fills the border box. A single-color gradient is an image, so it can be its own layer. Second, one box keyword in the shorthand sets both background-origin and background-clip. The border-box origin is what makes the gradient span the whole element; with the default padding-box origin, the gradient would be sized to the padding box and repeat into the border, creating visible seams.
The limitation is the center: it must be opaque, because the inner layer is what hides the gradient behind it. For theming, replace the hard-coded white with a custom property, for example linear-gradient(var(--surface), var(--surface)) padding-box. The gradient border generator outputs exactly this technique: pick two colors, an angle, a border width and a corner radius, check the preview card, and copy the CSS.
Technique 3: A Masked Pseudo-Element for Transparent Centers
When the element sits on a photo, a gradient or a glass panel, an opaque center is not acceptable. The solution is to draw the gradient on a pseudo-element and use a CSS mask to cut out the middle:
.outline {
position: relative;
border-radius: 16px;
padding: 1.5rem;
}
.outline::before {
content: "";
position: absolute;
inset: 0;
padding: 3px; /* border width */
border-radius: inherit;
background: linear-gradient(135deg, #14b8a6, #8b5cf6);
-webkit-mask:
linear-gradient(#000, #000) content-box,
linear-gradient(#000, #000);
-webkit-mask-composite: xor;
mask:
linear-gradient(#000, #000) content-box,
linear-gradient(#000, #000);
mask-composite: exclude;
pointer-events: none;
}
The pseudo-element covers the whole element and is filled with the gradient, and its padding sets the border thickness. The mask has two layers: one limited to the content box, everything inside the padding, and one covering the full box. mask-composite: exclude keeps only the areas where the layers do not overlap, which is exactly the padding ring. Because the pseudo-element inherits the radius, the outer edge curves and the inner edge follows a matching, slightly smaller curve.
- The
-webkit-declarations cover older Chromium and Safari versions that only understood prefixed masks, where the equivalent composite value isxor. Keep the standard declarations last so they win in current browsers. pointer-events: nonelets clicks pass through the ring to the content underneath.- The ring is drawn inside the element's edges, so give the element padding larger than the border width to keep content clear of it.
- The element itself can have any background, including none at all.
Which Gradient Border Technique Should You Use?
| Technique | Rounded corners | Transparent center | Needs a pseudo-element | Best for |
|---|---|---|---|---|
| border-image | No | Yes | No | Square boxes, single-side accents |
| padding-box / border-box | Yes | No | No | Cards, buttons and inputs on solid surfaces |
| Masked pseudo-element | Yes | Yes | Yes | Elements over images, gradients or glass |
For most product UI, the double background is the default choice: one rule, no extra elements, and it works with any radius. Reach for the mask only when the center truly needs to be see-through.
Animating a CSS Gradient Border
Both rounded techniques can be animated by registering an angle with @property and using it in a conic gradient:
@property --border-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.card {
border: 3px solid transparent;
border-radius: 16px;
background:
linear-gradient(#ffffff, #ffffff) padding-box,
conic-gradient(from var(--border-angle, 0deg), #14b8a6, #8b5cf6, #ec4899, #14b8a6) border-box;
animation: border-spin 6s linear infinite;
}
@keyframes border-spin {
to { --border-angle: 360deg; }
}
@media (prefers-reduced-motion: reduce) {
.card { animation: none; }
}
Repeating the first color at the end of the conic gradient avoids a hard seam where it wraps around, and the 0deg fallback inside var() leaves a static border in browsers without @property support. Our guide to animated gradient backgrounds in CSS covers @property, timing and performance in more depth, and the animated gradient generator is handy when you want a moving gradient behind the card as well.
Accessibility and Color Choices
If a gradient border is the only thing that shows the edge of an input or button, it identifies a user interface component, and WCAG asks for at least 3:1 contrast against adjacent colors. With a gradient, the weakest point counts, so check both end colors against the surrounding background in the color contrast checker. A light teal fading into pale lavender may look elegant on white yet leave part of the border nearly invisible. For focus states, do not rely on a gradient change alone; keep a clear outline or focus ring as well.
For the colors themselves, related hues usually look more refined than opposites. Preview angles and stops in the gradient generator first, and see creating multi-color CSS gradients if you want three or more stops in the ring.
Conclusion
Use border-image with a slice of 1 for square or single-side gradient borders, the padding-box and border-box double background for rounded elements with a solid fill, and a masked pseudo-element when the center must stay transparent. All three accept any CSS gradient, including animated conic gradients. To skip the trial and error for the most common case, build a rounded gradient border in the gradient border generator and paste the CSS straight into your stylesheet.
FAQ
Frequently Asked Questions
Why does border-radius not work with border-image?
The CSS specification states that border images are not clipped by border-radius, so the border stays square even when the element has rounded corners. This is intended behavior, not a browser bug. Use the padding-box and border-box double background or a masked pseudo-element when you need rounded gradient borders.
How do I make a gradient border with a transparent background?
Draw the gradient on an absolutely positioned pseudo-element, give it padding equal to the border width, and use two mask layers with mask-composite set to exclude so only the padding ring remains. The double background technique cannot do this because its inner layer must be opaque to hide the gradient underneath.
Can you animate a CSS gradient border?
Yes. Register an angle custom property with @property, use it as the starting angle of a conic gradient on the border layer, and animate the property from 0deg to 360deg in a keyframe animation. Remember to stop the animation inside a prefers-reduced-motion media query.
Can you use a gradient with the outline property?
No. The outline-color property only accepts colors, not images, so gradients are not allowed. For a gradient ring, use one of the border techniques or a pseudo-element, and keep a clearly visible solid outline for keyboard focus states.