摘要:使用3D硬件加速提升动画性能时,最好给元素增加一个z-index属性,人为干扰复合层的排序,可以有效减少chrome创建不必要的复合层,提升渲染性能,移动端优化效果尤为明显。 以下为原文:CSS3硬件加速也有坑!!! 常听人说:
移动端要想动画性能流畅,应该使用3d硬件加速最近深入了解了一些浏览器内核的细节,感觉这里面其实有坑啊。。。 事情要从最近看的《WebKit技术内幕》说起,第二章介绍了网页的结构,其中提到了Webkit硬件加速的方式,会把需要渲染的元素放到特定的『Composited Layer』中,在chrome的控制台可以这样开启:
层创建标准 什么情况下能使元素获得自己的层?虽然 Chrome 的启发式方法(heuristic)随着时间在不断发展进步,但是从目前来说,满足以下任意情况便会创建层:主要是最后一条,我觉得它的中文翻译不是很准确,原文其实是:
- 3D 或透视变换(perspective transform) CSS 属性
- 使用加速视频解码的 元素
- 拥有 3D (WebGL) 上下文或加速的 2D 上下文的 元素
- 混合插件(如 Flash)
- 对自己的 opacity 做 CSS 动画或使用一个动画 webkit 变换的元素
- 拥有加速 CSS 过滤器的元素
- 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在自己的层里)
- 元素有一个 z-index 较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)
Element has a sibling with a lower z-index which has a compositing layer (in other words the it’s rendered on top of a composited layer)这句话的意思是,如果有一个元素,它的兄弟元素在复合层中渲染,而这个兄弟元素的z-index比较小,那么这个元素(不管是不是应用了硬件加速样式)也会被放到复合层中。 最可怕的是,浏览器有可能给复合层之后的所有相对或绝对定位的元素都创建一个复合层来渲染,于是就有了上面那个项目截图的那种效果。之前一直奇怪为什么这个页面滚动很卡,明明没有多少DOM,现在看来问题就在这里了! 于是乎我写了一个页面,让大家看看这东西到底有多大威力:


setInterval('document.body.scrollTop++', 0);然后用timeline抓一下页面性能:

96.206 ms
!!这还是在我的mac系统上哦,手机上真的会卡出翔。
我在页面上放置了一个开关『为动画元素设置z-index』,这个checkbox点击之后,会用js给那个动画的h1元素加 position:relative
和 z-index: 1
,这种做法的原理是人为提升动画元素的z-index,让浏览器知道这个元素的层排序,就不会很傻逼的把其他z-index比它高的元素也弄到复合层中了,看看这个效果:


大家可以现在就排查一下这类问题,尤其是用了轮播、动画loading的页面,出现这问题很常见。另外推荐在追查性能问题的时候打开『show composited layer borders』选项,如果页面有很多黄色的框肯定是不对的。 最后,再次推荐一下《Webkit技术内幕》这本书。浏览器内核之于前端工程师,就如同操作系统之于后端工程师,毕竟是我们程序运行的宿主环境,多了解一些,很多问题容易想通。使用3D硬件加速提升动画性能时,最好给元素增加一个z-index属性,人为干扰复合层的排序,可以有效减少chrome创建不必要的复合层,提升渲染性能,移动端优化效果尤为明显。