30
头图

Recently, I saw this very interesting effect on CodePen:

The core difficulty of this effect is a special fusion effect of bubbles.

The source code is at: CodePen Demo -- Goey footer , the author mainly uses the SVG filter to complete the effect. If you are interested, you can check the source code.

Among them, in order to flexibly use the filters in SVG feGaussianBlur filters still need a very strong SVG knowledge reserve. So, is it possible to achieve this effect with just CSS?

Hey, strong CSS is certainly possible. In this article, I will lead you step by step to use pure CSS to achieve the above effects.

Complete the rough effect with SASS

First of all, if the above effect does not have the fusion effect of the bubbles, it may just be this:

It is relatively simple to make such an effect, but the code will be more, we can use the SASS preprocessor.

Suppose we have the following HTML structure:

 <div class="g-wrap">
  <div class="g-footer">
    <div class="g-bubble"></div>
    <div class="g-bubble"></div>
    // ... 200 个 g-bubble
  </div>
</div>

The core thing to do is to make 200 .g-bubble randomly perform upward animation from the bottom.

Here, we need to use a technique we introduced in this article on CSS animation in simple terms - using animation-duration and animation-delay to build random effects .

Build random effects with animation-duration and animation-delay

For the same animation, we use random within a certain range animation-duration and random within a certain range animation-delay , which can effectively construct a more random animation effect and make the animation more natural.

Let's simulate, if we use 10 circles that are consistent with animation-duration and animation-delay , the core pseudocode:

 <ul>
    <li></li>
    <!--共 10 个...--> 
    <li></li>
</ul>
 ul {
    display: flex;
    flex-wrap: nowrap;
    gap: 5px;
}
li {
    background: #000;
    animation: move 3s infinite 1s linear;
}
@keyframes move {
    0% {
        transform: translate(0, 0);
    }
    100% {
        transform: translate(0, -100px);
    }
}

In this way, the movement of the ball will be uniform like this:

To make the movement of the ball seem very random, you only need to make animation-duration and animation-delay both float within a certain range, and modify the CSS:

 @for $i from 1 to 11 {
    li:nth-child(#{$i}) {
        animation-duration: #{random(2000)/1000 + 2}s;
        animation-delay: #{random(1000)/1000 + 1}s;
    }
}

We use SASS's loop and random() function, let animation-duration be random in the range of 2-4 seconds, let animation-delay be random in the range of 1-2 seconds, so that , we can get very natural and different rising animation effects, basically no repeated pictures, and a good simulation of random effects:

CodePen Demo -- Random animation effect with range random animation-duration and animation-delay

Well, let's apply the above-mentioned techniques to the effect we want to achieve in this article. Let's take another look at the HTML structure:

 <div class="g-wrap">
  <div class="g-footer">
    <div class="g-bubble"></div>
    <div class="g-bubble"></div>
    // ... 200 个 g-bubble
  </div>
</div>

Core CSS code:

 .g-footer {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 86px;
    width: 100%;
    background: #26b4f5;
}

@for $i from 0 through 200 { 
    .g-bubble:nth-child(#{$i}) {
        position: absolute;
        background: #26b4f5;
        $width: random(100) + px;
        left: #{(random(100)) + '%'};
        top: #{(random(100))}px;
        width: $width;
        height: $width;
        animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite;
    }
}
@keyframes moveToTop {
    90% {
        opacity: 1;
    }
    100% {
        opacity: .08;
        transform: translate(-50%, -180px) scale(.3);
    }
}

here:

  1. We use the SASS random function $width: random(100) + px; to randomly generate div circles of different sizes
  2. Using SASS random function left: #{(random(100)) + '%'} , top: #{(random(100))}px random positioning based on parent element
  3. The core is animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite , so that the movement of all div circles is random

The above comprehensive results of (1) and (2) will generate such a layout, evenly distributed circles:

Note: For the convenience of understanding, I have hidden the color of the outermost layer g-footer , and added a black border to g-bubble

Next, if we replace the animation statement, use a uniform animation duration, remove the negative delay, and become animation: moveToTop 4s ease-in-out infinite , the animation will look like this:

The whole is neat and uniform, and there is no sense of clutter.

Using the random effect, animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite , you can get the above feeling that different bubbles rise randomly:

Add a fusion effect

Next, and the most important step, how to create a fusion effect between the bubbles and the bubbles, and between the bubbles and the bottom .g-footer ?

This technique has been mentioned frequently in many previous articles, which is to use the filter: contrast() filter and the filter: blur() filter.

If you don't know this trick, you can poke my article to see: CSS filter tricks and details you don't know

Briefly describe this technique:

Take out the two filters separately, and their functions are:

  1. filter: blur() : Set the Gaussian blur effect on the image.
  2. filter: contrast() : Adjust the contrast of the image.

However, when they "fit", a wonderful fusion phenomenon occurs.

Look carefully at the process of the intersection of the two circles. When the edge is in contact with the edge, a boundary fusion effect will be produced. The blurred edge of the Gaussian blur is eliminated through the contrast filter, and the Gaussian blur is used to achieve the fusion effect.

Based on this, we simply transform our CSS code, and the amount of code that needs to be added is very small:

 .g-wrap {
    background: #fff;
    filter: contrast(8);
}
.g-footer {
    // ... 其他保持一致
    filter: blur(5px);
}

It's as simple as that, add a white background color and a contrast filter to the parent container filter: contrast(8) , and add the child container filter: blur(5px) . In this way, we can get the fusion effect of the bubbles, basically getting what we want. The desired effect:

Use background-filter instead of filter to eliminate edges

but! There is a small problem with using filter: blur() .

Using the element of filter: blur() , the blur of the edge of the element is not enough, which will cause the effect to be distorted at the edge. Let's take a closer look at the edge of the animation:

How to solve it? It's easy to handle. Here, we try to use backdrop-filter to replace filter .

The difference between the two is that filter acts on the element itself, while backdrop-filter acts on all elements covered by the area behind the element, if you want to know more backdrop-filter information, you can poke my article: In -depth discussion of the similarities and differences between filter and background-filter .

Simply transform the code, the original code:

 .g-footer {
    // ... 
    filter: blur(5px);
}

Modified code:

 .g-footer {
    // ... 去掉 filter: blur(5px)
    &:before {
        content: "";
        position: absolute;
        top: -300px;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1;
        backdrop-filter: blur(5px);
    }
}

We do this by going to .g-footer filter: blur(5px) , through his pseudo-element, superimposing a new element on top of itself, and adding an alternative backdrop-filter: blur(5px) .

Of course, because the blur(5px) also needs to serve the fusion between bubbles, so in order to cover the entire animation area, we also set top: -300px to expand its scope of action.

In the end, we can perfectly reproduce the effect achieved by the SVG filter at the beginning of the article:

In the article, I omitted most of the basic CSS code, the complete code, you can click here: CodePen Demo -- Bubble Rises

at last

This article is very similar to the techniques used in the previous clever use of CSS to achieve cool charging animations , but this article also has some new knowledge points, you can take a look at it together.

Well, this is the end of this article, I hope it helps you :)

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


chokcoco
12.3k 声望18.5k 粉丝