CSS Border Animation
CSS Border Animation
Animating the border of a card using pseudo-elements is a great way to add visual interest to your website. Below is an example of how you can achieve this effect using CSS. The idea is to use ::before and ::after pseudo-elements to create animated borders around the card.
1
2
3
4
<div class="card">
<h2>Card Title</h2>
<p>This is a card with an animated border.</p>
</div>
1
2
3
4
5
6
7
8
9
10
.card{
margin: auto;
padding: 2em;
width: 300px;
background-color: blueviolet;
text-align: center;
border-radius: 10px;
position: relative;
}
Notice that the properity “position: relative”. When you apply position: relative; to an element, it also affects its pseudo-elements (::before and ::after). Here’s how:
How position: relative; affects pseudo-elements: 1. Relative to itself: The pseudo-element is positioned relative to the element it belongs to. 2. Doesn’t affect document flow: Even if the pseudo-element is moved, the parent element’s position remains unchanged. 3. Can be moved with absolute: If you set position: absolute; on a pseudo-element, it will be positioned relative to the nearest positioned ancestor (i.e., an ancestor with position: relative; or another positioning property like absolute or fixed).
1
2
3
4
5
6
7
.card::after{
content: "";
position: absolute;
height: 100%;
width: 100%;
background-color: blue;
}
When you apply position: relative to the .card and position: absolute to the ::after pseudo-element, the ::after pseudo-element is constrained by the boundaries of the .card container. This means its size and position are relative to the .card, and it cannot exceed the dimensions of the .card.
1
2
3
4
5
6
7
8
9
10
11
12
.card::after{
content: "";
position: absolute;
height: 100%;
width: 100%;
background-color: blue;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
padding:10px
}
We position the pseudo-element’s top-left corner in the center, then shift it by 50% using transform: translate(-50%, -50%) to ensure the pseudo-element is centered around the original element. Then, the padding will create a border effect.
Instead of background-color, the next line will achieve the rainbow effect border:
1
background-image: conic-gradient(red, yellow, green, blue, purple, red);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.card::after{
content: "";
position: absolute;
height: 100%;
width: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
padding:10px;
background-image: conic-gradient(red, yellow, green, blue, purple, red);
border-radius: 10px;
}
Next, we duplicate the element
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.card::after, .card::before{
content: "";
position: absolute;
height: 100%;
width: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
padding:3px;
background-image: conic-gradient(red, yellow, green, blue, purple, red);
border-radius: 10px;
}
Then, we add opacity and blur effect to ::before
1
2
3
4
.card::before{
filter: blur(1.5rem);
opacity: 0.7;
}
Next, replace the background-image property with the following value and you will understand how to animate the border. The percentange of transparent property affect how long the tail is.
1
background-image: conic-gradient(transparent 10%, rgb(0, 38, 255));
Next, we use gradient angle to animate the rotation.
1
background-image: conic-gradient(from 270deg, transparent 10%, rgb(0, 38, 255));
Create an angle variable, and use it in our animation!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.card::after, .card::before{
--angle: 0deg;
content: "";
position: absolute;
height: 100%;
width: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
border-radius: 10px;
padding:20px;
background-image: conic-gradient(from var(--angle), transparent 10%, rgb(0, 38, 255));
}
Next, create our animation called spin.
```css
animation: 3s spin linear infinite;
Animate the angle variable!
1
2
3
4
5
6
7
8
@keyframes spin {
from {
--angle: 0deg;
}
to {
--angle: 360deg;
}
}
However, css variable is not animatable, we will need to use @property
remove the line in pseudo element.
1
--angle: 0deg;
Add the following lines.
1
2
3
4
5
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
Here is the complete final code. Note: the before pseudo element add a shadow to the effect!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
.card{
margin: auto;
padding: 2em;
width: 300px;
background-color: blueviolet;
text-align: center;
border-radius: 10px;
position: relative;
}
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.card::after, .card::before{
--angle: 0deg;
content: "";
position: absolute;
height: 100%;
width: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
border-radius: 10px;
padding:5px;
background-image: conic-gradient(from var(--angle), transparent 10%, red, yellow, green, blue, purple, red);
animation: 3s spin linear infinite;
}
.card::before{
filter: blur(1.5rem);
opacity: 0.7;
}
@keyframes spin {
from {
--angle: 0deg;
}
to {
--angle: 360deg;
}
}