关于前端:使用纯-CSS-实现超酷炫的粘性气泡效果

3次阅读

共计 4026 个字符,预计需要花费 11 分钟才能阅读完成。

最近,在 CodePen 上看到这样一个十分有意思的成果:

这个成果的外围难点在于气泡的一种非凡交融成果。

其源代码在:CodePen Demo — Goey footer,作者次要应用的是 SVG 滤镜 实现的该成果,感兴趣的能够戳源码看看。

其中,要想灵活运用 SVG 中的 feGaussianBlur 滤镜还是须要有十分弱小的 SVG 常识储备的。那么,仅仅应用 CSS 是否实现该成果呢?

嘿嘿,弱小的 CSS 当然是能够的。本文,就将率领大家一步步应用纯 CSS,实现上述成果。

借助 SASS 实现大抵成果

首先,如果上述成果没有气泡的交融成果,可能就仅仅是这样:

要制作这样一个成果还是比较简单的,只是代码会比拟多,咱们借助 SASS 预处理器即可。

假如咱们有如下 HTML 构造:

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

外围要做的,仅仅是让 200 个 .g-bubble 从底部无规律的进行向上升起的动画。

这里,就须要使用咱们在 深入浅出 CSS 动画 这篇文章中所介绍的一种技巧 — 利用 animation-duration 和 animation-delay 构建随机成果

利用 animation-duration 和 animation-delay 构建随机成果

同一个动画,咱们利用肯定范畴内随机的 animation-duration 和肯定范畴内随机的 animation-delay,能够无效的构建更为随机的动画成果,让动画更加的天然。

咱们来模仿一下,如果是应用 10 个 animation-durationanimation-delay 都统一的圆的话,外围伪代码:

<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);
    }
}

这样,小球的运动会是这样的整齐划一:

要让小球的静止显得十分的随机,只须要让 animation-durationanimation-delay 都在肯定范畴内浮动即可,革新下 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;
    }
}

咱们利用 SASS 的循环和 random() 函数,让 animation-duration 在 2-4 秒范畴内随机,让 animation-delay 在 1-2 秒范畴内随机,这样,咱们就能够失去十分天然且不同的回升动画成果,根本不会呈现反复的画面,很好的模仿了随机成果:

CodePen Demo — 利用范畴随机 animation-duration 和 animation-delay 实现随机动画成果

好,咱们把上述介绍的技巧,套用到咱们本文要实现的成果中去,HTML 构造再看一眼:

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

外围的 CSS 代码:

.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);
    }
}

这里:

  1. 咱们利用了 SASS 随机函数 $width: random(100) + px;,随机生成不同大小的 div 圆形
  2. 利用 SASS 随机函数 left: #{(random(100)) + '%'}top: #{(random(100))}px 基于父元素随机定位
  3. 最为外围的是 animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite,让所有 div 圆的静止都是随机的

上述(1)、(2)综合后果,会生成这样一种布局,平均扩散排布的圆形:

注:这里为了不便了解,我暗藏了最外层 g-footer 的色彩,并且给 g-bubble 增加了彩色边框

接着,如果咱们替换一下 animation 语句,应用对立的动画时长,去掉负的提早,变成 animation: moveToTop 4s ease-in-out infinite,动画就会是这样:

整体是整齐划一,没有横七竖八的感觉的。

使用上随机成果,animation: moveToTop #{(random(2500) + 1500) / 1000}s ease-in-out -#{random(5000)/1000}s infinite,就能失去上述的,不同气泡随机回升的感觉:

增加交融成果

接下来,也是最重要的一步,如何让气泡与气泡之间,以及气泡和底部 .g-footer 之间产生交融成果呢?

这个技巧在此前十分多篇文章中,也频繁提及过,就是利用 filter: contrast() 滤镜与 filter: blur() 滤镜。

如果你还不理解这个技巧,能够戳我的这篇文章看看:你所不晓得的 CSS 滤镜技巧与细节

简述下该技巧:

独自将两个滤镜拿进去,它们的作用别离是:

  1. filter: blur():给图像设置高斯含糊成果。
  2. filter: contrast():调整图像的对比度。

然而,当他们“合体”的时候,产生了微妙的交融景象。

认真看两圆相交的过程,在边与边接触的时候,会产生一种边界交融的成果,通过对比度滤镜把高斯含糊的含糊边缘给干掉,利用高斯含糊实现交融成果。

基于此,咱们再简略革新下咱们的 CSS 代码,所须要加的代码量非常少:

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

就这么简略,父容器增加红色底色以及对比度滤镜 filter: contrast(8),子容器增加 filter: blur(5px) 即可,这样,咱们就能得气泡的交融成果,根本失去咱们想要的成果:

利用 backdrop-filter 代替 filter 打消边缘

然而!利用 filter: blur() 会有一个小问题。

使用了 filter: blur() 的元素,元素边缘的含糊度不够,会导致成果在边缘失真,咱们认真看看动画的边缘:

如何解决呢?也好办,在这里,咱们尝试利用 backdrop-filter 去替换 filter

两者之间的差别在于,filter 是作用于元素自身,而 backdrop-filter 是作用于元素背地的区域所笼罩的所有元素,如果你想理解更多对于 backdrop-filter 的信息,能够戳我的这篇文章:深入探讨 filter 与 backdrop-filter 的异同。

简略革新下代码,原代码:

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

革新后的代码:


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

咱们通过去到原来增加在 .g-footer 上的 filter: blur(5px),通过他的伪元素,叠加一层新的元素在它自身之上,并且增加了代替的 backdrop-filter: blur(5px)

当然,因为这里的 blur(5px) 还须要为气泡与气泡之间的交融服务,所以为了笼罩动画全区域,咱们还设置了 top: -300px,扩充了它的作用范畴。

最终,咱们就能完满的复刻文章一结尾,应用 SVG 滤镜实现的成果:

在文章中,我省去了大部分根底的 CSS 代码,残缺的代码,你能够戳这里:CodePen Demo — Bubble Rises

最初

本文与之前的 巧用 CSS 实现酷炫的充电动画 内应用的技巧十分相似,但本文也有一些新的知识点,大家能够联合着一起看看。

好了,本文到此结束,心愿对你有帮忙 :)

想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 — iCSS 前端趣闻 😄

更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。

如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

正文完
 0