A Different Way to Think About Borders
The border-image property is often relegated to decorative tricks, but it’s also a powerful tool for dynamic UI effects. Because it treats a border as a canvas for any image or gradient, it opens up possibilities that plain solid or dashed lines simply can't match. One compelling use case is animating the border image itself, turning a static frame into a living part of the interface.
There's a well-known limitation: border images don't follow the curvature of border-radius. That makes animating a border around rounded corners tricky. However, for elements with square or rectangular shapes, the effect is direct and visually striking.
The efficiency of border-image is a key advantage. It automatically replicates a design across all four sides, and the border-image-slice property gives you precise control over how much of the source image is used, similar to how background-size works. This makes it straightforward to create complex, cohesive borders without repeating background logic.
Setting Up the Stage
We start with a simple div containing formatted text:
<div class=card><strong>Bruce Wayne</strong></div>
The visual foundation is set with fixed dimensions and a background image:
.card {
width: 150px;
aspect-ratio: 0.69;
position: relative;
background: center/90% no-repeat;
background-image: url("batman.jpg");
}
To keep the text from sitting directly on the background, a bit of padding is applied.
For the border itself, we'll use a CSS gradient. It's a type of background image, and its behavior makes it ideal for demonstrating the animation principles. We'll define its longhand properties individually for clarity.
A basic linear-gradient produces the initial animated effect:
.card {
/* ... */
/* Creates a linear color */
border-image-source: linear-gradient(-45deg, red 0%, transparent 0%);
/* Controls how the gradient is carved */
border-image-slice: 1;
/* Sets the physical thickness of the border */
border-image-width: 5px;
}
You might notice a small gap between the animated border and the card's background. The border-image-outset property pushes the border away from the element's edge to fix this:
.card {
/* ... */
border-image-source: linear-gradient(-45deg, red 0%, transparent 0%);
border-image-slice: 1;
border-image-width: 5px;
/* Pushes the border away from the div */
border-image-outset: 5px;
}
To render the border, the border-image-source and border-image-width properties are essential. The gradient starts fully transparent. By placing both the red and transparent colors at 0%, there is no space for blending, and the transparent color (appearing later in the list) takes over the entire gradient from the start. Using border-image-slice: 1 creates 1px slices, resulting in a smooth, uniform fill across the border.
The Core Challenge: Animating Gradients
Standard CSS can't transition gradients directly because it involves interpolating the percentage-based positions of color stops. However, we can work around this by registering a custom property and animating that:
@property --p {
syntax: "<percentage>";
initial-value: 0%;
inherits: false;
}
This registered variable is then used in the gradient:
.card {
/* ... */
border-image-source: linear-gradient(-45deg, red var(--p), transparent 0%);
}
The animation is triggered on hover, transitioning the property --p from its default 0% to 100%:
.card {
/* ... */
border-image-source: linear-gradient(-45deg, red var(--p), transparent 0%);
/* ... */
&:hover {
--p: 100%;
}
}
This instructs the browser to animate the red color's final position all the way to the end. The result is a gradient that expands into a solid red, creating the illusion of the border drawing itself.
Beyond Linear: Conic Gradients
The same concept applies to other gradient types. For example, a conic-gradient introduces a different visual language. This approach animates both the border-image-slice value (using a registered property --n) and the angle of the conic gradient (using --a). The border-image-repeat: round property is critical here, as it tiles the slices to fit a whole number within the border, stretching or squeezing them as necessary for a perfect fit.
.card {
/* Creates a sharp, expanding color wheel using the custom angle variable */
border-image-source: conic-gradient(from 0deg, red 0deg, transparent 0%);
/* Repeats the sliced regions smoothly without clipping */
border-image-repeat: round;
border-image-width: 5px;
border-image-slice: 1;
}
Both custom properties are registered to allow for smooth transitions:
/* Registers a custom property for the border-image-slice */
@property --n {
syntax: "<number>";
initial-value: 1;
inherits: false;
}
/* Registers a custom property for the gradient angle */
@property --a {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
Note: It's possible to animate border-image-slice directly, but the visual result can vary between browsers. Registering a custom property offers more consistent control.
These properties are integrated into the main stylesheet:
.card {
border-image-source: conic-gradient(from var(--a), red var(--a), transparent 0%);
border-image-width: 5px;
border-image-slice: var(--n);
border-image-repeat: round;
}
Specifying exactly which properties to transition is beneficial for performance:
.card {
border-image-source: conic-gradient(from var(--a), red var(--a), transparent 0%);
border-image-width: 5px;
border-image-slice: var(--n);
border-image-repeat: round;
transition-property: --n, --a;
transition-duration: 0.6s;
}
The transition is then applied on hover:
.card {
border-image-source: conic-gradient(from var(--a), red var(--a), transparent 0%);
border-image-width: 5px;
border-image-slice: var(--n);
border-image-repeat: round;
transition-property: --n,--a;
transition-duration: 0.6s;
&:hover {
/* Increases slicing depth to repeat/tile the border pattern */
--n: 20;
/* Rotates the gradient full circle to draw the border in */
--a: 360deg;
}
}
The slice value (--n) starts at 1 and increases to 20 on hover, making the slices up to 20px thick. This change is visually apparent as breaks and patterns appear in the border, creating a striking, lively effect. This approach demonstrates that border-image isn’t just for static styling—it’s a canvas for motion and a robust way to build engaging interfaces.



