CSS 动画一站式指南( 六 )


4. CSS 动画性能优化回流又叫重排 , 指几何属性需要改变的渲染,例如当元素的尺寸 , 布局等发生变化时一般会引发回流 。重绘 , 指外观属性需要改变的渲染,例如当元素的背景色发生变化时一般会引发重绘 。
一个 CSS 动画往往会涉及尺寸 , 位置 , 颜色等属性的变化,如果处理不当就会引发不断地回流和重绘,导致页面卡顿,尤其在性能有限的移动端这种问题尤为严重 。
在上面提到,几何属性改变时一般会引发回流,外观属性改变时一般会引发重绘,那么在 CSS 中哪些属性是几何属性,哪些属性是外观属性呢?这里简单地总结了一下 。
几何属性:包括布局、尺寸等可用数学几何衡量的属性 。

  • 布局: displayfloatpositionlisttableflexcolumnsgrid
  • 尺寸: marginpaddingborderwidthheight
外观属性:包括界面、文字等可用状态向量描述的属性
  • 界面: appearanceoutlinebackgroundmaskbox-shadowbox-reflectfilteropacityclip
  • 文字: textfontword
我们知道回流一定会引发重绘,重绘不一定会引发回流 。回流成本比重绘成本高得多,一个节点的回流很有可能导致子节点、兄弟节点或祖先节点的回流 。频繁触发回流会使得页面不断渲染,从而引发严重的性能问题,因此我们一定要尽可能地避免回流,减少重绘 。
接下来介绍一些 CSS 动画性能优化的方法 。
4.1 使用 visibility:hidden 替换 display:none从以下四个方面对比一下display:nonevisibility:hidden  , 方便书写,display:none 简称DNvisibility:hidden简称VH
  • 占位表现
  • DN不占据空间
  • VH占据空间
  • 触发影响
  • DN触发回流重绘
  • VH触发重绘
  • 过渡影响
  • DN影响过渡不影响动画
  • VH不影响过渡不影响动画
  • 株连效果
  • DN后自身及其子节点全都不可见
  • VH后自身及其子节点全都不可见但可声明子节点 visibility:visible 单独显示
两者的 占位表现触发影响株连效果 就能说明 VH 代替 DN 的好处 , 如果两者都能实现需求的情况下推荐使用visibility:hidden
4.2 使用 transform 代替 toptop 是几何属性,操作 top 会改变节点位置从而引发回流,使用 transform:translate3d(x,0,0) 代替 top ,只会引发图层重绘 , 还会间接启动GPU加速 , 因此更加推荐使用 transform 来代替 top 。
4.3 避免使用 Table 布局当然 Table 布局现在已经很少用了 , 不过在这里还是提一下,来指出它所带来的问题,避免引入类似的问题 。牵一发而动全身用在 Table 布局身上再合适不过了,可能很小的一个改动就会造成整个 <table> 回流,大家如果感兴趣可以用 Chrome DevtoolsPerformance调试看看 。对于类似 table 布局的结构,建议用 <ul><li><span> 等标签进行取代 。
4.4 避免规则层级过多浏览器的CSS解析器在解析css文件时,对CSS规则是从右到左匹配查找的,样式层级过多会影响回流重绘效率,建议保持CSS规则在 3层 左右 。
4.5 避免节点属性值放在循环里当成循环变量像下面这段代码就存在很大的问题,每次循环操作 DOM 都会发生回流,应该在循环外使用变量保存一些不会变化的DOM 映射值 。
for (let i = 0; i < 10000; i++) {const top = document.getElementById("css").style.top;console.log(top);}建议修改为下面这样:
const top = document.getElementById("css").style.top;for (let i = 0; i < 10000; i++) {console.log(top);}4.6 将频繁回流重绘的节点设置为图层在浏览器中设置频繁回流或重绘的节点为一张新图层,因为新图层能够阻止节点的渲染行为影响别的节点 , 这张图层里如何变化都无法影响到其他图层 。

推荐阅读