Gradient borders in CSS


Safari 18.2 added a new value for the background-clip property: border-area.

It’s long been possible to implement a gradient border using the border-image property, but that approach isn’t compatible with setting a border-radius.

In the following example, both the background-color and background-image are clipped by background-clip: border-area.

.border-gradient {
    background-image: linear-gradient(35deg, #1B88FF, oklch(0.82 0.13 223.75));
    background-clip: border-area;
    background-origin: border-box;
    border: solid 4px transparent;
}

Jen Simmons wrote a post that explains how this works.

Together with a border gradient, you may also want a gradient or image that isn’t clipped to the border, fulfilling the role of a regular background.

background-image can specify multiple backgrounds, and each can be set to use a different background-clip value.

.border-gradient-and-background-gradient {
    background-image: linear-gradient(navy, aqua), linear-gradient(blue, white);
    background-clip: border-area, padding-box;
    background-origin: border-box;
    border: solid 4px transparent;
}

In the above code, one gradient uses a background-clip value of border-area while the other uses a value of padding-box. background-clip values name the area that a background is clipped into, so padding-box means the image is visible everywhere except the border area.

A single-color “gradient”

Something that landed in all (beta) browsers recently is the ability to use a single color as the value for a gradient (currently requires Safari Technology Preview, Firefox Nightly or Chrome Canary).

div {
    background-image: linear-gradient(green);
}

This works for linear-gradient, radial-gradient and conic-gradient.

This has very niche use-cases, but comes in handy to set a solid background color when working with background-clip: border-area.

.border-gradient-with-solid-bg {
    background-image: linear-gradient(35deg, #1B88FF, oklch(0.82 0.13 223.75)), linear-gradient(white);
    background-clip: border-area, padding-box;
    background-origin: border-box;
    border: solid 4px transparent;
}