渲染树构建、布局和绘制

Ilya Grigorik
Ilya Grigorik

发布时间:2014 年 3 月 31 日

CSSOM 树和 DOM 树合并成渲染树,然后在 计算每个可见元素的布局,并用作 将像素渲染到屏幕上的绘制流程。优化以上各项 对实现最佳渲染性能至关重要。

在前面介绍构建对象模型的章节中,我们根据 HTML 和 CSS 输入构建了 DOM 树和 CSSOM 树。不过,它们都是独立的对象,分别网罗文档不同方面的信息:一个描述内容,另一个则是描述需要对文档应用的样式规则。我们该如何将两者合并,让浏览器在屏幕上渲染像素呢?

摘要

  • DOM 树和 CSSOM 树组合成渲染树。
  • 渲染树只包含渲染网页所需的节点。
  • 布局会计算每个对象的精确位置和大小。
  • 最后一步是绘制,使用最终渲染树将像素渲染到屏幕上。

首先,浏览器将 DOM 和 CSSOM 合并成一个“渲染树”,用于捕获页面上所有可见的 DOM 内容以及每个节点的所有 CSSOM 样式信息。

结合使用 DOM 和 CSSOM 来创建渲染树

为构建渲染树,浏览器大致执行以下操作:

  1. 从 DOM 树的根节点开始遍历每个可见节点。

    • 某些节点不可见(例如脚本标记、元标记等),因为它们不会体现在渲染输出中,所以会被忽略。
    • 有些节点使用 CSS 隐藏,并且也会从渲染树中省略;例如,渲染树中缺少上例中的 span 节点,因为我们有一条明确设置“display: none”的规则属性。
  2. 对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。

  3. 发射可见节点,连同其内容和计算的样式。

最终输出的渲染树同时包含了屏幕上的所有可见内容及其样式信息。有了渲染树,我们就可以继续进行“布局”阶段。

到目前为止,我们已经计算了哪些节点应该可见以及它们的计算样式,但我们还没有计算它们在设备视口内的确切位置和大小,这就是“布局”这个阶段也被称为“自动重排”

为了弄清每个对象在网页上的确切大小和位置,浏览器会从渲染树的根节点开始进行遍历。请参考下面的示例:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Critial Path: Hello world!</title>
  </head>
  <body>
    <div style="width: 50%">
      <div style="width: 50%">Hello world!</div>
    </div>
  </body>
</html>

试试看

前面示例的 <body> 包含两个嵌套的 <div>:第一个(父级)<div> 将节点的显示尺寸设置为视口宽度的 50%,而第二个 <div>(由父级包含)将其 width 设置为其父级的 50%;也就是视口宽度的 25%

计算布局信息

布局流程的输出是一个“盒模型”,它会精确地捕获每个元素在视口内的确切位置和尺寸:所有相对测量值都转换为屏幕上的绝对像素。

最后,既然我们知道了哪些节点是可见的,以及它们计算出的样式和几何形状,我们就可以将这些信息传递给最后一个阶段,也就是将渲染树中的每个节点转换成屏幕上的实际像素。这一步通常称为“绘制”或“栅格化”。

这可能需要一些时间,因为浏览器需要完成很多工作。不过,Chrome DevTools 可以帮助我们对上述所有三个阶段进行深入的了解。查看最初“hello world”示例的布局阶段:

在开发者工具中衡量布局

  • “Layout”事件在时间线中捕获渲染树构建以及位置和尺寸计算。
  • 布局完成后,浏览器会立即发出“Paint Setup”和“Paint”事件,将渲染树转换成屏幕上的像素。

执行渲染树构建、布局和绘制所需的时间因文档大小、应用的样式和运行设备而异:文档越大,浏览器的工作量就越大;样式越复杂,绘制所需的时间就越长(例如,绘制纯色所需的时间较短,而绘制阴影所需的时间较长)。

最后,该网页会显示在视口中:

渲染的 Hello World 页面

下面简要回顾了浏览器的步骤:

  1. 处理 HTML 标记并构建 DOM 树。
  2. 处理 CSS 标记并构建 CSSOM 树。
  3. 将 DOM 和 CSSOM 合并成一个渲染树。
  4. 在渲染树上运行布局,以计算每个节点的几何图形。
  5. 将各个节点绘制到屏幕上。

演示页面看似很简单,实际上浏览器这方面需要做大量工作。如果 DOM 或 CSSOM 被修改,您必须重复此流程,以确定哪些像素需要在屏幕上重新渲染。

优化关键渲染路径就是指最大限度缩短执行上述第 1 步至第 5 步耗费的总时间。这样可以尽快将内容渲染到屏幕上,还可以缩短首次渲染后屏幕更新的间隔时间;即实现更高的互动内容刷新率

反馈