跳到主要内容

浏览器渲染原理

面试速答(30 秒版 TL;DR)

  • 浏览器渲染不是“拿到 HTML 直接显示”,而是要经历:解析 HTML 构建 DOM、解析 CSS 构建 CSSOM、合成 Render Tree、Layout、Paint、Composite
  • CSS 会阻塞渲染JS 可能阻塞解析和渲染;所以首屏性能优化本质上是在缩短渲染关键路径(Critical Rendering Path)。
  • 真正容易卡的地方通常不是“下载慢”一个点,而是:阻塞资源太多、主线程太忙、频繁布局和绘制
  • 一句话记忆:先把结构和样式算出来,再算位置,再画出来,最后交给合成线程上屏。

心智模型:浏览器在做两件事

你可以把浏览器渲染理解成两个连续问题:

  1. 页面长什么样? 这一步要解析 HTML、CSS,确定节点、样式、可见性。
  2. 页面怎么摆、怎么画、怎么上屏? 这一步要做布局、绘制、图层合成。

常见误区是把“解析”“布局”“绘制”混成一个动作。面试里最好拆开说,因为不同优化手段针对的是不同阶段。


关键流程:从字节到像素

1. 解析 HTML,构建 DOM

  • 浏览器把 HTML 字节流转成 Token,再生成 DOM 树。
  • DOM 描述的是文档结构,不负责最终样式和位置。
  • HTML 解析通常是增量式的,边下载边解析,不一定等整个 HTML 下载完才开始。

2. 解析 CSS,构建 CSSOM

  • CSSOM 描述的是每个节点最终可能应用的样式规则。
  • CSS 会影响后续布局和绘制,因此浏览器通常要等关键 CSS 到位,才能安全进入后续阶段。
  • 所以常说 CSS 是渲染阻塞资源

3. 合成 Render Tree

  • Render Tree 不是 DOM 的简单复制。
  • display: none 这样的节点不会进入 Render Tree。
  • 伪元素、匿名盒模型结构可能会进入 Render Tree。

4. Layout(布局 / 回流)

  • 根据 Render Tree 和盒模型规则,计算每个可见元素的几何信息:
    • 位置
    • 宽高
    • 盒子之间的关系
  • 这一步是后续绘制的前提。

5. Paint(绘制 / 重绘)

  • 把每个节点该怎么画记录成绘制指令。
  • 例如背景色、边框、文字、阴影、图片。

6. Composite(合成)

  • 浏览器可能会把部分内容拆成独立图层。
  • 合成线程把这些图层按顺序拼起来,最终显示到屏幕。
  • 这也是为什么 transformopacity 这类属性通常更适合做动画。

哪些资源会阻塞渲染

CSS 为什么会阻塞

因为浏览器在不知道最终样式前,无法可靠地做布局和绘制。如果先画出来、后面样式又变,会导致闪烁和重复计算。

JS 为什么会阻塞

因为 JS 可以直接改 DOM 和 CSSOM:

<script>
document.body.innerHTML = '<h1>new content</h1>'
</script>

如果浏览器一边解析、一边渲染,而 JS 又随时改结构,状态就会不一致。所以普通同步脚本会阻塞 HTML 解析;如果脚本依赖样式信息,也可能间接等待 CSS。


一个面试很好用的链路表达

先记住关键路径:请求资源、构建树、布局绘制,然后才有首屏可见。

面试时你可以总结为:

首屏慢,本质上不是单点问题,而是关键路径太长。要么资源来得慢,要么主线程被阻塞,要么渲染阶段反复重算。


典型优化抓手

1. 缩短关键资源链路

  • 减少首屏必须下载的 CSS/JS
  • 关键 CSS 尽量提前
  • 非关键 JS defer / 懒加载
  • 图片按需加载,首屏图高优先级

2. 减少主线程压力

  • 避免首屏执行过多同步 JS
  • 重计算丢到 Worker
  • 大列表做虚拟滚动

3. 减少渲染成本

  • 避免频繁读写布局属性
  • 动画优先 transform / opacity
  • 控制 DOM 深度和复杂样式

典型题 & 标准答法

Q1:浏览器渲染页面的过程是什么?

:浏览器先解析 HTML 构建 DOM,解析 CSS 构建 CSSOM,然后把两者合成 Render Tree。接着进行 Layout 计算元素几何信息,再进行 Paint 生成绘制指令,最后通过 Composite 把图层合成并显示到屏幕上。这里 CSS 会阻塞渲染,JS 可能阻塞解析和渲染,所以性能优化重点是缩短渲染关键路径。

Q2:为什么 CSS 会阻塞渲染?

:因为 CSS 会影响元素最终样式和布局。如果样式还没确定,浏览器无法安全地计算位置和绘制内容。为了避免错误绘制和反复重算,浏览器通常会等待关键 CSS 解析完成后再继续后续渲染流程。

Q3:为什么 transform 动画通常比改 top/left 更流畅?

top/left 往往会触发布局和绘制,而 transform 更容易只走合成阶段,不必每一帧都重新 Layout 和 Paint,所以更容易保持流畅。


常见追问

  • DOM 和 Render Tree 有什么区别?
  • display: nonevisibility: hidden 对渲染流程有什么影响?
  • asyncdefer 对渲染链路分别有什么影响?
  • 为什么“首屏 JS 太多”会让 LCP 变差?

易错点

  • 不要把 DOM 构建Render Tree 构建 说成一回事。
  • 不要把 LayoutPaint 混为一谈。前者算位置尺寸,后者负责画。
  • 不要机械地说“CSS 会阻塞 DOM 解析”。更准确地说:CSS 主要阻塞渲染,JS 是否阻塞解析取决于脚本加载与执行方式。

速记要点

  • DOM 决定结构,CSSOM 决定样式,Render Tree 决定可渲染对象。
  • Layout 算位置,Paint 负责画,Composite 负责上屏。
  • 性能优化重点不是背流程,而是知道瓶颈卡在哪一段。