浏览器的渲染过程
- 解析HTML,生成DOM树,解析CSS,生成CSSOM树
- 将DOM树和CSSOM树联合,生成渲染树(Render Tree)
- Layout(回流):依据生成的渲染树,进行回流(Layout),失去节点的几何信息(地位,大小)
- Painting(重绘):依据渲染树以及回流失去的几何信息,失去节点的相对像素
- Display:将像素发送给GPU,展现在页面上。
为了构建渲染树,浏览器次要实现了以下工作:
- 从DOM树的根节点开始遍历每个可见节点。
- 对于每个可见的节点,找到CSSOM树中对应的规定,并利用它们。
- 依据每个可见节点以及其对应的款式,组合生成渲染树。
第一步中,既然说到了要遍历可见的节点,那么咱们得先晓得,什么节点是不可见的。不可见的节点包含:
- 一些不会渲染输入的节点,比方script、meta、link等。
- 一些通过css进行暗藏的节点。比方display:none。留神,利用visibility和opacity暗藏的节点,还是会显示在渲染树上的。只有display:none的节点才不会显示在渲染树上。
回流
后面咱们通过结构渲染树,咱们将可见DOM节点以及它对应的款式联合起来,可是咱们还须要计算它们在设施视口(viewport)内的确切地位和大小,这个计算的阶段就是回流。
重绘
最终,咱们通过结构渲染树和回流阶段,咱们晓得了哪些节点是可见的,以及可见节点的款式和具体的几何信息(地位、大小),那么咱们就能够将渲染树的每个节点都转换为屏幕上的理论像素,这个阶段就叫做重绘节点。
何时产生回流
回流这一阶段次要是计算节点的地位和几何信息,那么当页面布局和几何信息发生变化的时候,就须要回流。比方以下状况:
- 增加或删除可见的DOM元素
- 元素的地位发生变化
- 元素的尺寸发生变化(包含外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比方文本变动或图片被另一个不同尺寸的图片所代替。
- 页面一开始渲染的时候(这必定防止不了)
- 浏览器的窗口尺寸变动(因为回流是依据视口的大小来计算元素的地位和大小的)
浏览器的优化机制
古代的浏览器都是很聪慧的,因为每次重排都会造成额定的计算耗费,因而大多数浏览器都会通过队列化批改并批量执行来优化重排过程。浏览器会将批改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。然而!当你获取布局信息的操作的时候,会强制队列刷新,比方当你拜访以下属性或者应用以下办法:
- offsetTop、offsetLeft、offsetWidth、offsetHeight
- scrollTop、scrollLeft、scrollWidth、scrollHeight
- clientTop、clientLeft、clientWidth、clientHeight
- getComputedStyle()
- getBoundingClientRect
缩小重绘与回流
CSS
- 应用 transform 代替 top
- 应用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(扭转了布局
- 防止应用table布局,可能很小的一个小改变会造成整个 table 的从新布局。
- 尽可能在DOM树的最末端扭转class,回流是不可避免的,但能够缩小其影响。尽可能在DOM树的最末端扭转class,能够限度了回流的范畴,使其影响尽可能少的节点。
- 防止设置多层内联款式,CSS 选择符从右往左匹配查找,防止节点层级过多。
- 将动画成果利用到position属性为absolute或fixed的元素上,防止影响其余元素的布局,这样只是一个重绘,而不是回流,同时,管制动画速度能够抉择 requestAnimationFrame,详见探讨 requestAnimationFrame。
- 防止应用CSS表达式,可能会引发回流。
- 将频繁重绘或者回流的节点设置为图层,图层可能阻止该节点的渲染行为影响别的节点,例如will-change、video、iframe等标签,浏览器会主动将该节点变为图层。
CSS3 硬件加速(GPU减速),应用css3硬件加速,能够让transform、opacity、filters这些动画不会引起回流重绘 。
JavaScript
- 防止频繁操作款式,最好一次性重写style属性,或者将款式列表定义为class并一次性更改class属性。
- 防止频繁操作DOM,创立一个documentFragment,在它下面利用所有DOM操作,最初再把它增加到文档中。
- 防止频繁读取会引发回流/重绘的属性,如果的确须要屡次应用,就用一个变量缓存起来。
- 对具备简单动画的元素应用相对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。