- 添加或者删除可见的DOM元素
- 元素位置改变
- 元素尺寸改变
- 元素内容改变(例如:一个文本被另一个不同尺寸的图片替代)
- 页面渲染初始化(这个无法避免)
- 浏览器窗口尺寸改变
CSS的最终表现分为以下四步:Recalculate Style -> Layout -> Paint Setup and Paint -> Composite Layers
按照中文的意思大致是 查找并计算样式 -> 排布 -> 绘制 -> 组合层
这上面的几个步骤有点类似于上文说到的重排必定导致重绘,而查询属性会强制发生重排。所以上文提到的重排重绘内容可以结合这里进行理解。
由于transform是位于Composite Layers层,而width、left、margin等则是位于Layout层,
在Layout层发生的改变必定导致Paint Setup and Paint -> Composite Layers,所以相对而言使用transform实现的动画效果肯定比left这些更加流畅。
而且就算抛开这一角度,在另一方面浏览器也会针对transform等开启GPU加速。
在 CSS 中,transforms 和 opacity 这两个属性更改不会触发重排与重绘,它们是可以由合成器(composite)单独处理的属性。
1.CSS
使用transform替代top
使用visibility替换display:none,因为前者只会引起重绘,后者会引发回流(改变了布局)
避免使用table布局,可能很小的一个改动会造成整个table的重新布局
尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围。
避免设置多层内联样式,css选择符从右往左匹配查找,避免节点层级过多。
将动画效果应用到position属性为absolute或者fixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流。同时,控制动画速度可以选择requestAnimationFrame。
避免使用css表达式,可能会引发回流。
将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-change,video,iframe等标签,浏览器会自动将该节点变为图层。
CSS3硬件加速(GPU加速),使用CSS3硬件加速,可以让transform,opacity,filters这些动画不会引起回流重绘。
2.JavaScript
避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性
避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。