跳到主要内容
7 分钟阅读

浏览器的运行原理

本文详细介绍了浏览器渲染页面的七个阶段(HTML解析、样式计算、布局、分层、绘制、分块、光栅化)以及reflow(回流)、repaint(重绘)的概念和transform效率高的原因。

浏览器渲染页面的过程可以分为七个阶段:

1. HTML解析

浏览器接收到服务器响应的HTML文档后,会首先解析HTML文档,构建DOM树。DOM树是由DOM元素及属性节点组成的,树的根是document对象。

2. 样式计算

浏览器会解析CSS文件和元素上的inline样式,计算出DOM节点的样式。这个过程包括:

  • 把CSS转换为浏览器能够理解的结构
  • 计算出DOM节点的具体样式

3. 布局

布局阶段会计算出DOM树中可见元素的几何位置,这个过程叫做布局或重排。

4. 分层

浏览器会根据布局后的DOM树,将其分为多个图层。这个过程主要是为了处理页面中的复杂效果,如3D变换、页面滚动等。

5. 绘制

在分层的基础上,浏览器会为每个图层生成绘制列表,并将其提交到合成线程。

6. 分块

合成线程会将图层划分为图块,这些图块的大小通常是256x256或者512x512。

7. 光栅化

合成线程会按照视口附近的图块来优先生成位图,这个过程叫做光栅化。光栅化过程中,会将图块转换为位图。

回流(Reflow)和重绘(Repaint)

回流(Reflow)

当我们对DOM的修改引发了DOM几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性,然后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。

引起回流的操作包括:

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见的DOM元素
  • 激活CSS伪类(例如::hover)
  • 查询某些属性或调用某些方法

一些常用且会导致回流的属性和方法:

  • clientWidth、clientHeight、clientTop、clientLeft
  • offsetWidth、offsetHeight、offsetTop、offsetLeft
  • scrollWidth、scrollHeight、scrollTop、scrollLeft
  • scrollIntoView()、scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

重绘(Repaint)

当我们对DOM的修改导致了样式的变化、但未影响其几何属性(比如修改了颜色或背景色)时,浏览器不需要重新计算元素的几何属性、直接为该元素绘制新的样式。这个过程叫做重绘。

相比回流,重绘的性能开销较小,因为重绘只是重新绘制元素的外观,而不需要重新计算元素的位置。

为什么transform效率高

transform是通过创建一个新的复合图层来实现的,这个复合图层会单独进行绘制,然后再与其他图层进行合成。这样,当我们使用transform进行变换时,只需要重新绘制这个复合图层,而不需要重新绘制整个页面。

使用transform可以避免回流和重绘,因为它不会影响到DOM的布局,只会影响到最终的渲染结果。这就是为什么使用transform进行动画会比直接修改元素的top、left等属性效率高的原因。

优化策略

为了减少回流和重绘,我们可以采取以下策略:

  1. 批量修改DOM:使用DocumentFragment或者先将元素设为display: none,然后进行多次修改,最后再显示。

  2. 避免频繁读取会引发回流/重绘的属性:如果必须多次读取,就将值缓存起来。

  3. 使用transform和opacity来实现动画效果:这两个属性不会触发回流。

  4. 使用will-change属性:这个属性可以提前告知浏览器元素将要发生的变化,浏览器可以提前做好优化工作。

  5. 使用绝对定位或固定定位:绝对定位和固定定位的元素发生变化时,只会影响自身,不会影响其他元素。

通过理解浏览器的渲染原理和优化策略,我们可以编写出更高效的前端代码,提升用户体验。

Joey Z.

Joey Z.

8 年企业系统、金融平台与区块链基础设施研发经验,关注架构、交付质量和代码的长期健康。