一个web页面由多层构成的
比如掘金:
浏览器渲染页面
在编写页面中,我们要知道浏览器如何处理
HTML
、
JavaScript
和
CSS
。
需要了解并注意五个主要区域, 这些我们拥有控制权的部分,也是像素至屏幕管道中的关键点。
每一步简介
- JavaScript。 一般来说,我们会使用 JavaScript 来实现一些视觉变化的效果。比如用 jQuery 的 animate 函数做一个动画、对一个数据集进行排序或者往页面里添加一些 DOM 元素等。当然,除了 JavaScript,还有其他一些常用方法也可以实现视觉变化效果,比如:CSS Animations、Transitions 和 Web Animation API。
- 样式计算。 此过程是根据匹配选择器(例如 .headline 或 .nav > .nav__item)计算出哪些元素应用哪些 CSS 规则的过程。从中知道规则之后,将应用规则并计算每个元素的最终样式。
- 布局。 在知道对一个元素应用哪些规则之后,浏览器即可开始计算它要占据的空间大小及其在屏幕的位置。网页的布局模式意味着一个元素可能影响其他元素,例如 元素的宽度一般会影响其子元素的宽度以及树中各处的节点,因此对于浏览器来说,布局过程是经常发生的。
- 绘制。 绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个表面(通常称为层)上完成的。
- 合成。 由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。
ps: 当然,不是每一步更改都会遵循上图这个流程。
每一步不是必经的
比如:
-
更改了元素的布局相关的属性:
width
,height
,位置
... 那么浏览器就会检查其他元素,自动重排一次
。 -
更改了元素的
color
,阴影
... 不会影响页面的布局,那么浏览器就会跳过布局。这就是我们平常说的:重排一定引起重绘,重绘不一定引起重排
。 - 如果更改了 一个既不会布局,也不会绘制的属性,那么浏览器直接跳到最后一步,不得不说,这是最高效的
使用 csstriggers 可以详细看到 css 属性改变时触发的流程。
如何提升绘制的性能
尽量使用影响较少的属性
举个🌰:
<div class="box box1">1</div>
<div class="box box2"> 2 </div>
<script>
const box1 = document.querySelector('.box1');
setTimeout(() => {
box1.style.display = 'none'
}, 3000);
</script>
复制代码
我们可以看到,
box1
和
box2
都绿(重绘)了一次,说明
box1
的变化影响了
box2
。那这个属性变化的代价是比较大的。
假如是我让
box1
的位置 向右移动
60px
,我们做如下更改:
document.querySelector('.box1').style.transform = 'translateX(60px)';
复制代码
现在
box2
的位置不受影响,直观地看到
box2
是没被绿(重绘)的。
提升为合成层(Compositing Layers)
我们在上一步做了优化,
box2
已经不受影响,但是
box1
依然被重绘,那能不能在优化呢。
答案是能的。
left 这个属性的改变会造成的影响是:
layout -> painted -> composited
复制代码
这个流程可以在 csstriggers 看到。
答案是有的:
transform
:影响最小,直接到达最后一步
Composite
。
做如下更改:
box1.style.transform = 'translateX(60px)'
复制代码
好像事与愿违。
box1
,
box2
都被重绘了。
这里因为:
他们都在一个层上,一个元素的变化也影响了其他元素。浏览器会联合需要绘制的区域,而导致整个屏幕重绘。
为了直接到达最后一步
Composite
。其实这里有个条件:
更改属性所在的元素应处于其自身的合成层,如果没在,我们可以提升为合成层`
这样就不会影响其他元素,而能减少绘制区域。
提升为合成层的原因有一下几种
这里我大概罗列了这么多
- video
- 有 3D transform
- backface-visibility 为 hidden
- 对 opacity、transform、fliter、backdropfilter 应用了 animation 或者 transition(需要是 active 的 animation 或者 transition,当 animation 或者 transition 效果未开始或结束后,提升合成层也会失效)
- will-change 设置为 opacity、transform、top、left、bottom、right(其中 top、left 等需要设置明确的定位属性,如 relative 等)
- 重叠原因
在
box1
上面做如下更改: