再回首CSS3动画
文章目录
众所周知CSS3动画性能手段的铁律之一就是,尽量不要使用会导致重排重绘的属性,之前看到这个后,就囫囵吞枣记住了,之后都会使用这个手段来优化性能,然而每次被人问起为什么要使用transform变换代替top/left等时,我都会说因为transform不会导致重绘…, 事实上原理并不是太清楚。
经过文档查阅,浏览器渲染CSS的步骤其实为:
Recalculate Style
-> Layout
-> Paint Setup and Paint
-> Composite Layers
即:查找并计算样式 -> 排布 -> 绘制 -> 组合层
注意:
- 查询属性会导致重排。
- 最后这个
组合层
,其实类似于PS中的图层概念, 浏览器中的元素通常也是有多个层的,经过一系列计算后,还要经过GPU组合图层才渲染出页面的。 - 重排必然导致重绘,重绘不一定触发重排。
为什么使用transform
可以优化性能:
transform
属性改变,发生在Composite Layers
这一层,所以不会经过前面的重排,重绘;并且还会触发GPU加速。从而大大提升性能。
与transform
属性类似的还有opacity
,也是直接在Composite Layers
这一层处理透明度。
其他优化手段
直接在元素上可以使用
box-shaodw
属性做动画:See the Pen Button hover effects with box-shadow by Giana (@giana) on CodePen.
需要注意的是,直接在DOM元素上改变box-shaodw
性能不如在元素的伪类上改变box-shaodw
属性。参见这里(配合chrome开发者工具的timeline可以明显查看性能差异)浏览器有图层概念,一个’图层’上可以有N个DOM元素,而且如果图层中某个元素需要重绘,那么整个图层都需要重绘。 比如gif图渲染每一帧,都会导致所在图层重绘,那就应该将gif元素独立出来达到优化目的。
附:Chrome中满足以下任意情况就会创建图层:
- 3D或透视变换(perspective transform)CSS属性
- 使用加速视频解码的
<video>
节点 - 拥有3D(WebGL)上下文或加速的2D上下文的
<canvas>
节点 - 混合插件(如Flash)
- 对自己的opacity做CSS动画或使用一个动画webkit变换的元素
- 拥有加速CSS过滤器的元素
- 元素有一个包含复合层的后代节点(一个元素拥有一个子元素,该子元素在自己的层里)
- 元素有一个z-index较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)