In the past, I’ve covered several ways to implement wave effects using pure CSS, and there are two related articles on them:

  • Pure CSS for wave effects!
  • Smart use CSS to achieve cool charging animation

This article will introduce another wave effect using CSS, which is very interesting.

Starting from the definite integral to achieve the curved triangle area

Now, before we get into this, in advanced mathematics, we can use definite integrals to figure out the curve area of a quadratic function.

We can divide the area under the curve into n thin rectangles, and as n infinity approaches infinity, the area of all the rectangles is equal to the area of the curved shape.

Two simple diagrams from why can a definite integral find the area? :

As n infinity approaches infinity, the area of all rectangles is equal to the area of the curved shape:

Using this idea, we can also simulate a curved edge, also known as a wavy line, in CSS with multiple divs.

Step 1. Cut the figure into multiple pieces

First, we can define a parent container with 12 child divs under it:

<div class="g-container">
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
  <div class="g-item"></div>
</div>
Copy the code

Using Flex layout, a simple layout results in a shape with each child element of equal height:

.g-container {
    width: 200px;
    height: 200px;
    border: 2px solid #fff;
    display: flex;
    align-items: flex-end;
}

.g-item {
    flex-grow: 1;
    height: 60px;
    background-color: #fff;
}
Copy the code

The effect is as follows:

Step 2. Have each child element run the height shift animation with a different negative delay

Next, in a simple twist, we need to animate the diagram by changing the height of each child element:

.g-item {
    flex-grow: 1;
    height: 60px;
    background-color: # 000;
    animation: heightChange 1s infinite ease-in-out alternate;
}

@keyframes heightChange {
    from {
        height: 60px;
    }
    to {
        height: 90px; }}Copy the code

The effect is as follows:

Next, we just need to set the animation sequence of each child element with a negative delay of different time to get a preliminary wave effect. Here, to reduce the workload, we use SASS to achieve:

$count: 12;
$speed: 1s;

.g-item {
    --f: #{$speed / -12};
    flex-grow: 1;
    height: 60px;
    background-color: # 000;
    animation: heightChange $speed infinite ease-in-out alternate;
}

@for $i from 0 to $count {
    .g-item:nth-child(# {$i + 1{})animation-delay: calc(var(--f) * #{$i}); }}@keyframes heightChange {
    from {
        height: 60px;
    }
    to {
        height: 90px; }}Copy the code

Thus, we have a preliminary wave effect:

Step 3. Remove serrations

As you can see, the wave animation above has a certain amount of jagged, the next thing we need to do is to eliminate these jagged as much as possible.

Method 1: Increase the number of divs

According to the original idea of using definite integrals to find the area of curved edges, we just need to increase the number of child divs as much as possible. When the number of divs is infinite, the sawtooth will disappear.

We can try to replace the above 12 child divs with 120. Try writing 120 divs one by one is too laborious, so we use the Pug template engine here:

div.g-container
 -for(var i=0; i<120; i++)
    div.g-item
Copy the code

For CSS code, we only need to change the animation delay time, and the negative delay of 120 child divs is controlled within 1s:

// 12 -- 120
$count: 120;
$speed: 1s;

.g-item{// Note that this is the only change --f: #{$speed / -120};
    flex-grow: 1;
    height: 60px;
    background-color: # 000;
    animation: heightChange $speed infinite ease-in-out alternate;
}

@for $i from 0 to $count {
    .g-item:nth-child(# {$i + 1{})animation-delay: calc(var(--f) * #{$i}); }}Copy the code

This gives us a smoother curve:

Method 2: Radians are simulated by transform: Skew ()

Of course, using so many divs would be a waste of time, but are there other ways to eliminate the aliasing as much as possible with fewer divs?

Here, we can try adding a different transform: skewY() to the child element to simulate radians.

To tweak the code again, we lowered the number of divs and added a Transform: skewY() animation for each child div:

div.g-container
 -for(var i=0; i<24; i++)
    div.g-item
Copy the code

The complete CSS code is as follows:

$count: 24;
$speed: 1s;

.g-item{// Note that this is the only change --f: #{$speed / -24};
    flex-grow: 1;
    height: 60px;
    background-color: # 000;
    animation: 
        heightChange $speed infinite ease-in-out alternate,
        skewChange $speed infinite ease-in-out alternate;
}

@for $i from 0 to $count {
    .g-item:nth-child(# {$i + 1{})animation-delay: 
            calc(var(--f) * #{$i}), 
            calc(var(--f) * #{$i} - #{$speed / 2}); }}@keyframes heightChange {
    from {
        height: var(--h);
    }
    to {
        height: calc(var(--h) + 30px); }}@keyframes skewChange {
    from {
        transform: skewY(20deg);
    }
    to {
        transform: skewY(-20deg); }}Copy the code

To make it easier to understand, let’s first look at how skewY() is added to the subdiv with the same height transform animation:

It can be seen that each transform has a sharp jagged edge, and when combined with the delayed height transform, most of the jagged effect can be removed nicely:

At this point, we have another way of removing aliasing with a modest number of divs! Full code for all of the above effects, you can poke here:

CodePen — PureCSS Wave Effects

A mixture of

Finally, we can combine several different wave effects by adjusting several variable parameters and get some combination effects, which is also nice.

Something like this:

CodePen — PureCSS Wave Effects 2

Based on this, I am reminded of the LOGO of Sea Group, the parent company of Shopee, which looks like this:

Using the scheme in this paper, to achieve a dynamic LOGO animation:

CodePen Demo — PureCSS Wave – Sea Group Logo

disadvantages

The drawbacks are obvious:

  • The first is the waste div, need more div to achieve the effect, and the more div, the better the effect will be, of course, increase to a certain degree, the lag is inevitable
  • The sawtooth can’t be completely removed, and this is the most deadly or bad place where it can really be used

Of course, the purpose of this paper is to expand the focus of thinking, discuss the advantages and disadvantages of this way, the whole process of animation, animation negative delay time application, are some reference learning significance. CSS is fun ~ 🤣

The last

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

Want to Get the most interesting CSS information, do not miss my public account – iCSS front-end interesting news 😄

More interesting CSS technology articles are summarized in my Github — iCSS, constantly updated, welcome to click on the star subscription favorites.

If there are any questions or suggestions, you can exchange more original articles, writing is limited, talent and learning is shallow, if there is something wrong in the article, hope to inform.