浏览器layers和css层级上下文,浏览器渲染合成和优化

题目取得很大,实际上我还没读懂一些文章,先把笔记记在这里,希望以后能慢慢搞懂这个问题,再持续补充文档。

从一个css样式引发的思考。

前几天,遇到了一个问题:某一个div A使用了transform样式,导致另一个div B中fixed属性失效,fixed div B直接形成了absolute的效果,而它的参照父级变成了A。
查找资料
https://www.zhangxinxu.com/wordpress/2015/05/css3-transform-affect/
以下属性都会造成类似的效果:

  • 具有以下任一属性的元素,并且其值不是 none:
    transform
    filter(滤镜)
    perspective
    clip-path(裁剪)
    mask/ mask-image/mask-border
    mix-blend-mode的值不是normal的元素。
    属性isolation(隔离)的值为isolate的元素。

理由是:transform属性会造成元素在垂直地位上的提升,也有说法是会形成新的BFC,导致文档流按照新的BFC布局。

看到有人说是“垂直层级”上升,我就好奇了,css的层级,和浏览器的渲染层级,有什么关系?为什么transform会造成垂直层级上升。

然后翻到了这几篇资料:
https://blog.csdn.net/qq_39446719/article/details/102980947
https://juejin.cn/post/6844903966573068301

大概总结一下

就是有关又无关,css的层级有可能会使它在浏览器分层,但是大部分都不会造成分层效果。
浏览器的分层主要指的是在渲染中,浏览器会根据render树生成布局(layout)树和层树,然后再重排重绘渲染。

分层只是为了z轴方向上的展示次序吗?
不,分层的重要性比我们想象中大的多。

你有时候可能会产生疑惑,一个css动画一直在页面上修改修改,到底要导致重绘重排多少次?制造多大的花销?
嗯,浏览器也是这么考虑的,因此它引入了一个不同于重排重绘的第三个渲染机制:合成

也就是分层与合成

让不涉及到文字信息、颜色、布局等改变的一部分元素单独分一个合成层出来优化渲染,不要去影响大部分其他正常渲染的元素。

浏览器内有多个线程,大部分重绘和回流都是在 渲染线程内完成的,也就是某个页面的渲染主线程,所以会卡顿之类的。但是合成是在合成线程内完成的,所以相对于渲染线程是独立的,有时候你看到浏览器卡了但是仍然能滑动、动画仍然正常出现,可能是这样的原因。

提升了性能,集中了处理资源。
(但是也增加了css各种魔幻事件~orz)


可以使用devtool中的layers选项看到层级。
浏览器layers和css层级上下文,浏览器渲染合成和优化_第1张图片


在浏览器渲染过程中,每个 DOM 节点都会对应一个 LayoutObject,当他们的 LayoutObject 处于相同的坐标空间时,即 Z 轴上位于同一平面,就会形成一个 RenderLayers ,也就是渲染层,此文简称 Layer。

Layer 将同一坐标空间的 LayoutObject 组织起来,保证页面元素以正确的顺序合成,这时候就会出现层合成(composite)。

某些特殊的渲染层会被认为是 合成层。合成层拥有单独的处理单元(GraphicsLayer),而其他不是合成层的渲染层 Layer,则和第一个拥有独立处理单元的父层共用一个处理单元。

那么上文的层叠上下文除了能帮助我们正确了解和处理元素在 Z 轴上的展示意外,当我们对层叠上下文进行优化处理时,可以得到 合成层 的 css 性能优化。

但是 层叠上下文 与 Layer 之间的关系可以 笼统地概括为:有自己的 layer 的元素则必定是一个层叠上下文,而是层叠上下文的元素不一定有自己的 layer。

(引用自上文资料)


浏览器内有几个概念:
1、渲染对象(RenderObject)
2、渲染层(RenderLayer)
3、图形层(GraphicsLayer)
4、合成层(CompositingLayer)

每一个DOM节点是一个渲染对象。
一个合成层内可能有很多渲染层和渲染对象,一个图形层对应一个合成层,图形层内有图形上下文,可以帮助合成层渲染。

然后浏览器是以合成层为单位去渲染一层动画的。

比如:(以下内容来自参考文档+我的理解,如果有错误日后再订正)
一个普通filter滤镜元素会被分离出一个单独的渲染层(RenderLayer),但是它仍然没有分离出一个单独的合成层(CompositingLayer),它和document元素共用一个合成层。
但是如果加上了will-change属性,浏览器会自动把它升格为一个合成层,然后用GPU 加速去渲染这个单独层级,也就是硬件加速。
浏览器layers和css层级上下文,浏览器渲染合成和优化_第2张图片
浏览器layers和css层级上下文,浏览器渲染合成和优化_第3张图片

那么一个渲染层满足哪些特殊条件时,才能被提升为合成层呢?这里列举了一些常见的情况:

3D transforms:translate3d、translateZ 等

video、canvas、iframe 等元素

通过 Element.animate() 实现的 opacity 动画转换

通过 СSS 动画实现的 opacity 动画转换

position: fixed

具有 will-change 属性

对 opacity、transform、fliter、backdropfilter 应用了 animation 或者 transition

掘金的那篇文章还提到了隐式提升、层爆炸、层压缩,都蛮有意思的。


这部分可以给我们的指导意义: 尝试利用层提升的特性优化性能,避免无意识的隐式提升。

最后看开头的问题,transform的效果是因为垂直层级的提升吗?应该不是的,它没有提升层级,应该是CSS的渲染特性BFC造成了这样的效果。

w3c 对 transform 的定义

For elements whose layout is governed by the CSS box model, any value other than none for the transform property also causes the element to establish a containing block for all descendants. Its padding box will be used to layout for all of its absolute-position descendants, fixed-position descendants, and descendant fixed background attachments.

你可能感兴趣的:(前端,css)