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 same border-image line paints just that side.
  • Elements whose background you do not control, because border-image does 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:

  1. The border is transparent, so whatever background sits beneath it shows through.
  2. The second layer, the gradient, uses border-box, so it fills the entire element including the border area.
  3. The first layer is painted on top and uses padding-box, so it covers everything except the border, leaving only a gradient ring visible.
  4. 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 is xor. Keep the standard declarations last so they win in current browsers.
  • pointer-events: none lets 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?

TechniqueRounded cornersTransparent centerNeeds a pseudo-elementBest for
border-imageNoYesNoSquare boxes, single-side accents
padding-box / border-boxYesNoNoCards, buttons and inputs on solid surfaces
Masked pseudo-elementYesYesYesElements 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.