Colour · gradient recipeCSS gradient border — with rounded corners
border-image draws a gradient border but breaks border-radius. Two backgrounds are more reliable: a solid one under the content and the gradient under the border.
Give the border a width and make it transparent — the background shows through it.
02
linear-gradient(#fff, #fff) padding-box
The first layer is the solid backing colour, limited to the padding box.
03
linear-gradient(…) border-box
The second layer is the gradient itself, stretched to the outer edge of the border.
04
border-radius: 14px
The radius applies to both layers at once.
04
Common mistakes
border-image and rounded corners
With border-image, border-radius is ignored. If you need corners, use two backgrounds.
Backing differs from the page
The first layer must match the colour under the card, otherwise a visible plate appears around the content.
Transparent card
The trick needs an opaque backing. Semi-transparent cards need a mask (mask-composite) — a separate technique.
05
Frequently asked
That is how the specification works: border-image replaces the normal border painting with an image, and corner rounding is not applied to that image. So a gradient border made with border-image always has sharp corners, whatever border-radius says. The two-background trick in this recipe avoids the limitation: the border stays transparent, the gradient is painted as a background beneath it, and the radius applies to both layers.
The two-background trick needs an opaque backing, so a transparent card needs a mask. Put the gradient on a ::before pseudo-element with padding equal to the border width and cut out the middle: mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0), plus mask-composite: exclude and -webkit-mask-composite: xor for Safari. Only a ring along the edge remains, and the page shows through beneath it.
The simple way is to stretch the second layer with background-size: 200% 200% and move its background-position in @keyframes, leaving the backing layer alone. A rotating border comes from conic-gradient and an angle variable declared with @property using the angle syntax, which browsers can animate. This works in Chrome 85+, Safari 16.4+ and Firefox 128+. Add a prefers-reduced-motion block that turns it off.
The width comes from an ordinary border: 3px solid transparent — the gradient shows exactly in that band. Change the number and the border changes, while the background layers follow by themselves because they are tied to padding-box and border-box. A thin one or two pixel border looks good with contrasting colours; from six pixels the transition itself becomes visible. The slider on this page goes from 1 to 12 pixels.
Use the same two-background trick: the backing becomes the field colour and the gradient layer becomes the border. It is handy to show the gradient only on focus: the border is grey normally, and under :focus-visible the second layer switches to the gradient. Do not remove the outline without a replacement — the gradient border is the replacement, but it must stand out: at least two pixels wide with 3:1 contrast against the background.
Yes: comma-separated backgrounds and clipping a layer with padding-box and border-box have been supported for more than ten years, including old Safari versions and mobile browsers. No prefixes are needed. The only thing an old browser may reject is the gradient itself with in oklch, so for a border it is sensible to keep sRGB blending or lay the transition out with intermediate stops.