仅为参考文章中需要记忆的内容整理,建议优先阅读浏览器层合成与页面渲染优化
渲染层(RenderLayer)
这是浏览器渲染期间构建的第一个层模型,处于相同坐标空间(z轴空间)的渲染对象,都将归并到同一个渲染层中,因此根据层叠上下文,不同坐标空间的的渲染对象将形成多个渲染层,以体现它们的层叠关系。所以,对于满足形成层叠上下文条件的渲染对象,浏览器会自动为其创建新的渲染层。
浏览器会为其创建新的渲染层的元素
能够导致浏览器为其创建新的渲染层的,包括以下几类常见的情况:
-
根元素
document
-
有明确的定位属性(
relative、fixed、sticky、absolute
) -
opacity < 1
-
有 CSS
fliter
属性 -
有 CSS
mask
属性 -
有 CSS
mix-blend-mode
属性且值不为normal
-
有 CSS
transform
属性且值不为none
-
backface-visibility
属性为hidden
-
有 CSS
reflection
属性 -
有 CSS
column-count
属性且值不为auto
或者有 CSScolumn-width
属性且值不为auto
-
当前有对于
opacity、transform、fliter、backdrop-filter
应用动画 -
overflow
不为visible
合成层(CompositingLayer)
满足某些特殊条件的渲染层,会被浏览器自动提升为合成层。合成层拥有单独的 GraphicsLayer,而其他不是合成层的渲染层,则和其第一个拥有 GraphicsLayer 的父层共用一个。
被提升为合成层的渲染层元素
那么一个渲染层满足哪些特殊条件时,才能被提升为合成层呢?这里列举了一些常见的情况:
-
3D transforms
:translate3d
、translateZ
等 -
video、canvas、iframe
等元素 -
通过
Element.animate()
实现的opacity
动画转换 -
通过 СSS 动画实现的
opacity
动画转换 -
position: fixed
-
具有
will-change
属性 -
对
opacity
、transform
、fliter
、backdropfilter
应用了animation
或者transition
可以利用 will-change
属性,将 CPU 消耗高的渲染元素提升为一个新的合成层,才能开启 GPU 加速的,因此你也可以使用 transform: translateZ(0)
来解决这个问题。
层合成的得与失
层合成是一个相对复杂的浏览器特性,为什么我们需要关注这么底层又难理解的东西呢?那是因为渲染层提升为合成层之后,会给我们带来不少好处:
-
合成层的位图,会交由 GPU 合成,比 CPU 处理要快得多;
-
当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层;
-
元素提升为合成层后,transform 和 opacity 才不会触发 repaint,如果不是合成层,则其依然会触发 repaint。
当然了,利弊是相对和共存的,层合成也存在一些缺点,这很多时候也成为了我们网页性能问题的根源所在:
-
绘制的图层必须传输到 GPU,这些层的数量和大小达到一定量级后,可能会导致传输非常慢,进而导致一些低端和中端设备上出现闪烁;
-
隐式合成容易产生过量的合成层,每个合成层都占用额外的内存,而内存是移动设备上的宝贵资源,过多使用内存可能会导致浏览器崩溃,让性能优化适得其反。(⭐解决方法:使用更高的
z-index
,规避隐式生成不必要的合成层)
浏览器层合成情况查看方法
层合成情况,点击 More tools
-> Layers
,你可以看到像这样的一个视图:
左侧列出了所有提升为独立合成层的元素,右侧则是一个整体合成层边界视图,以及选定合成层的详细情况,包括以下几个比较关键的信息:
- Size:合成层的大小,其实也就是对应元素的尺寸;
- Compositing Reasons:形成复合层原因,这是最关键的,也是我们分析问题的突破口,比如图中的合成层产生的原因就是交叠问题;
(⭐描述为: Composition due to association with an element that may overlap other composited elements.)
- Memory estimate:内存占用估算;
- Paint count:绘制次数;
- Slow scroll regions:缓慢滚动区域。