Skip to content

浏览器的渲染流程,从 URL 到像素

浏览器从输入 URL 到页面渲染出来,中间经历的过程我以前大概能说个七八成,但总有些细节是模糊的。这次整理笔记,干脆把整个链路理了一遍。

主要阶段

1. 构建 DOM 树

浏览器收到 HTML 后,会逐字节解析,把标签转成节点,再生成 DOM 树。过程中如果遇到 <script> 标签,会暂停解析去下载和执行脚本——这也是为什么建议把 JS 放在 body 底部。

2. 构建 CSSOM 树

CSS 的解析和 HTML 类似,但 CSS 是"层叠"的,涉及到优先级计算,比 HTML 解析复杂一些。不过 CSS 解析不会阻塞 DOM 树构建,但会阻塞渲染——因为浏览器需要等 CSSOM 就绪才能确定每个元素的样式。

3. 生成渲染树

DOM 树 + CSSOM 树 = 渲染树。但渲染树不是简单的合并,它会过滤掉不可见的节点(比如 display: none 的元素),只保留需要绘制的内容。

4. 布局

确定每个元素的位置和大小。这个过程是递归的——父元素的位置会影响子元素,子元素的大小也会反过来影响父元素。所以布局阶段会从根节点开始,逐级计算。

5. 绘制

把布局结果转换成屏幕上的像素。浏览器会把绘制内容分层(比如固定定位的元素单独一层),然后按层绘制,最后合成。

关键优化点

  • CSS 放在 head 里:尽早开始 CSSOM 构建,缩短阻塞渲染的时间
  • JS 放在 body 底部,或用 defer/async:避免阻塞 DOM 解析
  • 减少回流:回流是布局阶段的重新计算,成本很高。能用 transform 就尽量不用 top/left

回流和重绘的区别

  • 回流:元素的尺寸、位置变了,浏览器需要重新计算布局。比如修改 width、margin、padding。
  • 重绘:元素的样式变了但布局没变,比如修改 color、background。

回流的代价比重绘大得多,因为回流之后一定会有重绘。所以性能优化的一个核心思路就是:尽量减少回流。

整理完这个流程,我对"script 放哪里""为什么用 transform 更好""CSS 加载会不会阻塞"这些面试题的理解,就不再是背答案了,而是能从头推到尾。