Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS 阴影动画优化技巧一则 #71

Open
chokcoco opened this issue Oct 11, 2019 · 1 comment
Open

CSS 阴影动画优化技巧一则 #71

chokcoco opened this issue Oct 11, 2019 · 1 comment

Comments

@chokcoco
Copy link
Owner

chokcoco commented Oct 11, 2019

本技巧来自这篇文章 -- How to animate box-shadow with silky smooth performance

本文不是直译,因为觉得这个技巧很有意思很有用,遂起一文。

box-shadow 在我们的工作中使用以及越来越多,伴随阴影的动画或多或少都有一点。假设,我们有下面这样一个盒子:

div {
    width: 100px;
    height: 100px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

希望 hover 的时候,盒阴影从 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3) 过渡到 box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3)

  • box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3) --> box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3)

OK,最简单的方法当然是:

div:hover {
    width: 100px;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

因为过渡动画是在两个不同的盒阴影状态在发生,所以在过渡动画的时间内,浏览器会不断的重绘盒阴影。而又由于阴影属于耗性能样式,所以这种动画给人的感觉多少有些卡顿。

这里有一个小技巧可以优化这种情况下的阴影动画。

使用伪元素及透明度进行优化

使用伪元素及透明度进行优化,我们给上述元素添加一个 before 伪元素,大小与父 div 一致,并且提前给这个元素添加好所需要的最终的盒阴影状态,但是元素的透明度为 0。

div {
    position: relative;
    width: 100px;
    height: 100px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

div::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
    opacity: 0;
}

然后,在 hover 的时候,我们只需要将伪元素的透明度从 0 设置为 1 即可。

div:hover::before {
    opacity: 1;
}

这样做的好处是,实际在进行的阴影变化,其实只是透明度的变化,而没有对阴影进行不断的重绘,有效的提升了阴影动画的流畅程度,让它看起来更加丝滑。

bshadow

为什么对透明度 opacity 进行动画要比对 box-shadow 进行动画性能更好呢?可以看看这里这张表格,列举了不同属性变换对页面重排、重绘的影响:

image

very few CSS properties

最后,Demo 可以看看:

CodePen Demo -- 优化box-shadow动画

存在的问题,另外一种方案

原文中上述这个方案其实并不算太完美,因为最终的效果是两个阴影的叠加效果,可能会在整体的感觉上阴影颜色更深了一点。

所以需要对最终状态的阴影进行微调一下,削弱一点效果,尽量让两个阴影的叠加效果与单一一个阴影效果相近。

当然,我们可以再对上述方案进行优化,我们再使用一个 ::after 伪元素,::after 伪元素设置为初始状态且透明度为1,::before 伪元素设置为末尾状态且透明度为0:

div {
    position: relative;
    width: 100px;
    height: 100px;
}

div::before {
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
    opacity: 0;
}

div::after {
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

实际 hover 的时候,对两个伪元素进行一显一隐,这样最终的效果只有一个阴影效果,没有阴影的叠加,与直接对阴影进行过渡变化效果一致:

div:hover::before {
    opacity: 1;
}

div:hover::after {
    opacity: 0;
}

bshadow2

CodePen Demo -- 优化box-shadow动画

最后

好了,本文到此结束,希望对你有帮助 :)

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

最后,新开通的公众号求关注,形式希望是更短的篇幅,质量更高一些的技巧类文章,包括但不局限于 CSS:

image

@isdotjim
Copy link

搭个车...
想邀请Repo参与者来w3c.group创建项目的对应小组。w3c.group是类似知识星球的社群工具,小组可设置为付费且有赞助功能,同时也是一个区块链主导的创作者社区。这是相关介绍:
http://t.cn/Ai1vLcCU
http://t.cn/Ai1vLcCG
http://t.cn/Ai1vLcCA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants