Post

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;
    }
}
This post is licensed under CC BY 4.0 by the author.