Application of advanced CSS skills in complex dynamic effects

Time:2022-11-25

Recently I saw this interesting animation on CodePen:

Application of advanced CSS skills in complex dynamic effects

The whole animation effect is in one tag, realized with the help of SVG PATH. At its core is thegradient(Gradient) ultimate utilization.

You can see the full code here —CodePen DEMO — to the future 🍻 By Jane Ori]

The source code is still very, very complicated, and superimposed with complicated SVG PATH paths.

I tried to split it into several small pieces, and re-implemented it from another direction using different high-level CSS techniques. Because there are still many interesting CSS techniques in the whole process, this article will share them with you.

Realize the background of the first half plus the setting sun

First, let’s implement the background and sunset effect of the upper part:

<img width=”581″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187644739-3ea988df-6e78-4936-ad82-ecba5338d303.png”>

Everyone can stop and think for a while, here is what you are asked to do, how will you do it? How many labels are needed?

Ok, here, we use a DOM tag to complete this graphic:

<div class="g-bg"><div>

The background color is easy to do, just use a radial or linear gradient:

.g-bg {
    background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
}

So, get a simple background:

Application of advanced CSS skills in complex dynamic effects

OK, next, let’s use one of thePseudo-element implementing sunsetEffect.

.g-bg {
    position: absolute;
    background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
    
    &::before {
        content: "";
        position: absolute;
        bottom: 20%;
        left: 10%;
        right: 10%;
        top: 10%;
        background: radial-gradient(circle at 50% 100%, var(--color3), var(--color4) 55%, transparent 55.1%, transparent);
    }
}

The effect is as follows:

<img width=”585″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187646274-4f1f070a-9b42-4f80-ac65-e4e2fd886a0a.png”>

At this point, I think the first trick has appeared, which is this line of codebackground: radial-gradient(circle at 50% 100%, var(--color3), var(--color4) 55%, transparent 55.1%, transparent), which is used to achieve a semicircle in a rectangular element with a radial gradient from solid to transparent.

Tip 1: You can use the radial gradient to achieve a semicircle in a rectangular DIV element by changing the radial gradient from solid color to transparent color

Let’s continue, next, cut this circle to get such an effect:

<img width=”851″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187648068-97115342-e98d-4da9-a274-a02a5ae630d4.png”>

Note that the part that needs to be cut here is not white, but transparent, and the background color behind needs to be revealed.

There is no doubt that this needs to be done using a mask. We add a mask to the pseudo-element:

.g-bg {
    position: absolute;
    background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
    
    &::before {
        content: "";
        position: absolute;
        bottom: 20%;
        left: 10%;
        right: 10%;
        top: 10%;
        background: radial-gradient(circle at 50% 100%, var(--color3), var(--color4) 55%, transparent 55.1%, transparent);
        mask: linear-gradient(to top,
            #000 0, #000 10%,
            transparent 10%, transparent 13%,
            #000 13%, #000 20%,
            transparent 20%, transparent 22%,
            #000 22%, #000 35%,
            transparent 35%, transparent 36%,
            #000 36%, #000 100%);
    }
}

In this way, we achieve this effect:

<img width=”529″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187648493-be115a64-c57f-4697-98c3-5eff4c042409.png”>

Here, leads to the second trick:

Tip 2: Use the mask to crop the graphics, and the cropped area will become transparent.

Ok, next, we need to superimpose vertical black stripes on the entire graphic. In fact, this can also use a mask, if there is a black background behind the entire graphic.

Of course, here we can also use another pseudo-element, and use it to realize the vertical black stripes here through multiple linear gradients (repeating-linear-gradient).

Take a look at the code:

.g-bg {
    position: absolute;
    background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
    
    &::before {
        content: "";
        // code of sun
    }

    &::after {
        content: "";
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
        background: repeating-linear-gradient(90deg, transparent 0, transparent 3px, rgba(0,0,0,.5) 4px, rgba(0,0,0,.5) 5px);
    }
}

Here, we userepeating-linear-gradientQuickly create a batch of vertical black stripes to get this effect:

<img width=”548″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187652524-f2aaba8e-08ba-427f-9144-52d07e6dc113.png”>

Here, get tip 3.

Tip 3: When you encounter a large number of repeated and regular lines, or square graphics, you should immediately think of using gradients in one DOM instead of multiple DOMs to achieve

Well, at this point, we have achieved the entire first half.

Realize reflection with -webkit-box-reflect

With the above foundation, next we have to get the complete background:

<img width=”577″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187654739-741fc449-9f95-4918-803a-3f896d7013bc.png”>

How to do it? Do you want to re-implement it with a different color scheme? Of course not, here we use the reflection function provided by CSS to quickly complete this operation.

.g-bg {
    position: absolute;
    background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
    -webkit-box-reflect: below;

    &::before {
        content: "";
        // ...
    }
    &::after {
        content: "";
        // ...
    }
}

we give.g-bgadd one-webkit-box-reflect: below, meaning the reflection below:

<img width=”575″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187655575-acc52b7b-c75e-4861-8997-4f5546f8fd6a.png”>

Although it is an identical copy.g-bgcome out, but the effect is still far from what we want, what should I do?

don’t worry-webkit-box-reflect: belowIt also provides properties such as reflection offset distance and reflection mask.

We need to add a mask to the reflection below and modify it-webkit-box-reflectthe code:

.g-bg {
    position: absolute;
    background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
    -webkit-box-reflect: below -50px linear-gradient(rgba(255, 255, 255, .2), transparent);

    &::before {
        content: "";
        // ...
    }
    &::after {
        content: "";
        // ...
    }
}

In this way, we get such an effect:

<img width=”596″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187661797-9035b246-1b9c-4e98-8589-1aa5b8f26251.png”>

Here, the whole graphic is actually translucent. We superimpose a layer of color gradient we want on the back, and we can use the pseudo-element of body:

body {
    &::before {
        position: absolute;
        content: "";
        top: 50%;
        left: 0;
        bottom: 0;
        right: 0;
        background: linear-gradient(var(--c5), var(--c6));
    }
}
.g-bg {
    position: absolute;
    background: radial-gradient(circle at 50% 100%, var(--color1), var(--color2));
    -webkit-box-reflect: below -50px linear-gradient(rgba(255, 255, 255, .2), transparent);

    &::before {
        content: "";
        // ...
    }
    &::after {
        content: "";
        // ...
    }
}

The reflection is superimposed through translucency and the gradient background behind it, so that we can perfectly achieve the overall background effect we want:

<img width=”577″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187654739-741fc449-9f95-4918-803a-3f896d7013bc.png”>

Here, we can introduce technique 4.

Tip 4: When repeated symmetrical figures appear,-webkit-box-reflectMight come in handy.

Realize line animation with CSS 3D animation

Ok, the background of the main body is finished, let’s try to realize the 3D line animation:

Application of advanced CSS skills in complex dynamic effects

Using CSS 3D, we can achieve such an effect. Let’s break it down step by step.

First, we need to implement such a grid effect:

<img width=”525″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187662899-16bb8ac1-1f8b-40b9-a5ee-5b039fa40aa1.png”>

Remember tip 3 above? When you encounter a large number of repeated and regular lines, or square graphics, you should immediately think of using gradients in one DOM instead of multiple DOMs.

For this effect, in fact, it is enough to use a gradient label group:

<div class="grid"></div>
.grid {
    background:
        repeating-linear-gradient(var(--c1), var(--c1) 1px, transparent 1px, transparent 20px),
        repeating-linear-gradient(90deg, var(--c1), var(--c1) 1px, transparent 1px, transparent 20px);
}

That’s all, we get a grid map.

Ok, next, you need to use transform to make him present a 3D vision:

body {
    perspective: 300px;
}
.grid {
    position: absolute;
    width: 300vw;
    height: 600px;
    left: -100vw;
    top: 55vh;
    transform-style: preserve-3d;
    background:
        repeating-linear-gradient(var(--c1), var(--c1) 1px, transparent 1px, transparent 20px),
        repeating-linear-gradient(90deg, var(--c1), var(--c1) 1px, transparent 1px, transparent 20px);
    transform: translate3d(0, 0, 0) rotateX(90deg);
    transform-origin: 50% 0;
}

The effect is as follows:

<img width=”739″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187663962-cbff25e5-89c1-42ec-a4c8-f2e337a396f9.png”>

Since the whole rotates 90° around the X axis, so heretop: 55vhVery important.

Since the center of rotation is50% 0,in the case oftop: 50vh, which means that the whole graph will be vertical to the screen, iftopIf the value is less than 50vh, the entire grid is an upward flip effect:

Application of advanced CSS skills in complex dynamic effects

Next, we need to make it move.

Let’s try to add a translateZ motion animation:

.grid {
    // ...
    animation: move 10s infinite linear;
}
@keyframes move {
    0% {
        transform: translate3d(0, 0, -600px) rotateX(90deg);
    }
    100% {
        transform: translate3d(0, 0, 600px) rotateX(90deg);
    }
}

Take a look at the effect:

Application of advanced CSS skills in complex dynamic effects

There is a very serious problem here, just a single animation, it is difficult to achieve infinite loop connection.

Therefore, we need to add another set of Grid, and the two sets of animations start successively to realize the connection of the entire animation.

<div class="grid"></div>
<div class="grid"></div>
.grid {
    // ...
    animation: move 10s infinite linear;
}
.grid:nth-child(2) {
    animation: move 10s infinite -5s linear;
}
@keyframes move {
    0% {
        transform: translate3d(0, 0, -600px) rotateX(90deg);
    }
    100% {
        transform: translate3d(0, 0, 600px) rotateX(90deg);
    }
}

We do this in such a way:

  1. Two sets of identical animations, the entire displacement length is 1200px, the entire animation lasts for 10s, and the slow motion is a linear animation
  2. After the first group set off for 5 seconds (just traveled 600px), the second group set off again, so infinite repeats
  3. The entire 3D animation looks like an infinite loop effect on the near screen
  4. Here is used-5s, which means starting 5s in advance, the actual animation effect will not have a sense of waiting

As follows (here, in order to record GIF, I speed up the animation as a whole):

Application of advanced CSS skills in complex dynamic effects

It can be seen that the animation near the screen is continuous, but there will be a certain amount of flickering at the far end. Here, tip 5 is available.

Tip 5: Using 2 sets of animations can achieve some continuous effects that cannot be achieved by animations that are effective in a single set

In this way, superimposing the above effects, we get such an effect:

Application of advanced CSS skills in complex dynamic effects

As you can see, it’s very close. There is still some jitter in the distance of the line animation. It just so happens that we are short of the effect of a mountain peak, which can block this blemish.

Use box-shadow and SVG filter to achieve mountain effect

OK, finally, we can superimpose a mountain peak in the middle of the screen.

Here, the original effect is using a long list of exported SVG paths. If we don’t have such resources, we just want to simply simulate the effect. Here I give a possible solution.

I first use a rounded rectangle to rotate, and then match the container’soverflow: hiddento get a small peak:

<div class="g-mountain"></div>
.g-mountain {
    position: absolute;
    left: 0;
    right: 0;
    top: 15%;
    bottom: 42%;
    overflow: hidden;
    
    &::after {
        content: "";
        position: absolute;
        top: 78%;
        background: #011d3f;
        width: 15vw;
        height: 15vw;
        transform: rotate(-45deg);
    }
}

Probably something like this:

<img width=”208″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187668374-e2efecd3-6ee5-47f1-98d9-f273123d6734.png”>

Well, what should we do if we want to get multiple such graphics repeatedly? Multiple DOMs? No, here we can usebox-shadowcopy itself.

.g-mountain {
    // ...
    &::after {
        content: "";
        position: absolute;
        top: 78%;
        background: #011d3f;
        width: 15vw;
        height: 15vw;
        transform: rotate(-45deg);
        box-shadow: 
            -3vw -3vw, 5vw 5vw, 
            10vw 10vw 0 3vw, 15vw 20vw 0 4vw, 
            22vw 22vw 0 6vw, 25vw 30vw 0 12vw, 
            38vw 36vw 0 1vw, 41vw 39vw 0 3vw, 
            45vw 45vw 0 2vw, 52vw 52vw 0 4vh, 
            55vw 55vw 0 1.5vw, 61vw 61vw 0 0.5vw, 68vw 68vw 0 0;
    }
}

In this way, we use a label to realize a series of “mountains”:

<img width=”832″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187669194-3dd2983a-bdf6-478a-9eb6-8a12d2d7630c.png”>

Here, we get to tip 6.

Tip 6:box-shadowIt can effectively copy itself, and can use the fourth parameter, the diffusion radius, to enlarge itself proportionally.

In fact, at this point, a relatively rough restoration is completed. Of course, there is a small problem that the peaks should not be straight lines. Is it possible to create a curved outline effect?

This is difficult to achieve using pure CSS. Of course, fortunately, we can use the SVG filter mentioned many times before.

usefeTurbulenceCan effectively achieve some wave texture effects. And it can be quickly introduced through CSS filter.

<div class="g-mountain"></div>
<svg width="0">
  <filter id="filter">
    <feTurbulence id="turbulence" type="fractalNoise" baseFrequency=".03" numOctaves="20" />
    <feDisplacementMap in="SourceGraphic" scale="30" />
  </filter>
</svg>
.g-mountain {
    // ...
    filter: url('#filter');   

    &::after {
    }
}

Here, the originally neat and uniform straight lines suddenly became chaotic, looking more like the outline of a mountain range:

<img width=”801″ alt=”image” src=”https://user-images.githubusercontent.com/8554143/187670726-b262c845-51b3-41e2-a49d-61bc66060228.png”>

Here, we arrive at tip 7.

Tip 7: SVG filters can be quickly introduced through CSS filters. SVG filters can achieve some things that CSS cannot do, such as some special textures, ripples, smoke grains and other effects.

Ok, so far, we have roughly re-implemented the above animation according to our own understanding, and then made some simple modifications. The final effect is as follows:

Application of advanced CSS skills in complex dynamic effects

CodePen Demo — Pure CSS to the future

at last

Today’s content is a bit much, and the skills are also very fierce. All the techniques in this article have appeared very frequently in my previous articles. If you don’t know the details, you can search through keywords in iCSS and make up for it.

Well, this is the end of this article, I hope this article is helpful to you 🙂

More wonderful CSS technical articles are summarized in myGithub — iCSS, continuously updated, welcome to click a star to subscribe to the collection.

If you have any questions or suggestions, you can communicate more. Original articles have limited writing skills and lack of knowledge. If there are any inaccuracies in the article, please let me know.

Recommended Today

Centos8 installs and uses Ansible (2)

Ansible is an open source configuration management tool that we use to automate tasks and deploy applications. Using Ansible, you can automate routine tasks such as updating systems, installing software, and configuring services. Configuring the /etc/hosts file makes it troublesome to use the ip address. You can add the host name corresponding to the node […]