CSS gradients on borders
To apply a gradient to a border, the most straightforward approach is to use the border-image property (similarly to how it's done with background gradients):
.card--gradient-1 {
border-width: 4px;
border-style: solid;
border-image: linear-gradient(to right, darkblue, darkorchid) 1;
}
The '1' after the linear-gradient declaration is the border-image-slice value. By using 1, we specify we want a single border region.
The issue with this approach is that you can't combine border-image with border-radius, which is common requirement most designs.
.card--gradient-1 {
/* .. */
border-image: linear-gradient(to right, #802dcd, #f7943e) 1;
border-radius: 50em; /* 👈 not working */
}
A better approach
There's a better solution, based on the background-clip
property, that is compatible with the border-radius property.
.card--gradient-2 {
background: linear-gradient(var(--color-bg), var(--color-bg)) padding-box, linear-gradient(to right, #802dcd, #f7943e) border-box;
border-radius: 2rem;
border: 4px solid transparent;
}
The padding-box
and border-box
values specified after the linear gradients represent the background-clip
values.
The first linear gradient is limited to the padding box (i.e. all the content of the element, except the borders). It's a 'fake' gradient because we're using the same color twice; we're using it to mask the second background gradient with the background color.
The second gradient sits below the first one and is used to apply the desired gradient colors. Unlike the first one, the second gradient covers the border area (background-clip: border-box).
Finally, the transparent border is required to separate the border-box from the padding box (otherwise they would be identical and the first gradient would completely cover the second one).
A step further
It feels good to make things shiny ✨
But all that shines is not gold, browser support is a bit sketchy from hereThe animation of gradients is something that has been near impossible until the addition of CSS Houdini to our frontend toolkit. Along with many awesome features, Houdini provides us the @property
CSS At-Rule which gives you a registered custom property, as if you had called CSS.registerProperty
in Javascript. You can read more about the @property
from the docs or from this post.
We can define the angle of our gradient with a custom property.
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 180deg;
}
The angle can then be applied to our gradient declaration and then update on hover by updating the --angle
property value, pair this with a transition and you have an animated gradient.
.card--gradient-2 {
--angle: 180deg; /* 👈 browser coverage */
background: linear-gradient(var(--color-bg), var(--color-bg)) padding-box, linear-gradient(var(--angle), #802dcd, #f7943e) border-box;
border-radius: 2rem;
border: 4px solid transparent;
transition: --angle 500ms;
}
/* rotate the border on hover */
.card--gradient-2:hover {
--angle: 0deg;
}