现代浏览器渲染html已摒弃传统五步模型,核心是渐进式dom构建、按需样式计算生成computedstyle、layouttree替代render tree、paint输出指令而光栅化生成像素、合成层优化transform性能。

浏览器渲染 HTML 不再是简单的“DOM + CSSOM → Render Tree → Layout → Paint”五步老模型,现代浏览器(Chrome 110+、Firefox 120+)已重构核心流程,关键差异点直接决定你答对还是答错。
DOM 构建阶段会提前中断并输出部分结果
DOM 解析是渐进式的:浏览器收到部分 HTML 字节流就立即开始 tokenizer 和 tree builder,不需要等整个文件下载完。这意味着 document.write、同步 <script></script> 或 document.getElementById 在解析中途调用,可能只拿到不完整 DOM。
- 预加载扫描器(preload scanner)会并行提取
<link rel="stylesheet">、<img>、<script></script>的 URL,但不执行解析 - 遇到未加
async或defer的<script></script>,主线程会暂停 DOM 构建,等待脚本下载、解析、执行完毕才继续 -
<script type="module"></script>默认异步且 defer,但有模块依赖图,执行时机晚于普通defer
CSSOM 已被弃用,“样式计算”才是真实阶段
所谓 CSSOM 树在 Chromium 源码中并不存在独立数据结构;实际是“样式计算”(Recalculate Style)阶段,直接产出每个 DOM 节点的 ComputedStyle 对象。浏览器不会先建一棵 CSS 规则树再匹配,而是按需计算。
-
document.styleSheets返回的是CSSStyleSheet列表,不是“CSSOM 树”——它只是规则容器,不含节点映射关系 - 继承和层叠发生在计算时:父元素
font-size: 1.2rem被标准化为 px 后,子元素才继承该值;!important影响的是计算优先级,不是存储结构 - 媒体查询(
@media (prefers-color-scheme: dark))和自定义属性(var(--color))都在此阶段动态求值,不是静态构建结果
LayoutTree 替代了旧版 Render Tree,且不可见节点不参与布局
现代渲染引擎(Blink / WebKit)构建的是 LayoutTree,它只包含 display 值非 none 且参与盒模型计算的节点。visibility: hidden 元素仍在 LayoutTree 中,display: none 则彻底剔除。
-
、<meta>、<script></script>等非渲染元素不会进入 LayoutTree,哪怕它们有样式 -
position: fixed或含transform的元素可能触发新LayoutObject子树,但不会导致整棵树重排 - DevTools 的 Elements 面板里右键 “Scroll into view” 失效,常是因为该元素已被从 LayoutTree 剔除(如父级
display: none)
Paint 不等于像素,光栅化(Raster)才是生成位图的关键环节
“绘制”在开发者口中常指 Paint 阶段,但实际输出屏幕像素的是后续的光栅化(Raster):Paint 生成的是绘图指令列表(DisplayList),Raster 线程才真正把指令转成 GPU 可读的位图 Tile。
- 启用
chrome://tracing查看Paint和Rasterize事件,会发现两者时间不重合,且 Raster 可能跨帧延迟 -
will-change: transform或opacity会提前创建合成层(Composited Layer),跳过 Paint → Raster 流程,直接交由 GPU 合成 - 频繁修改
top/left触发 Layout + Paint + Raster 全链路,而transform: translateY()只走合成层更新,性能差一个数量级
面试时若还按“DOM/CSSOM/Render Tree”老三段讲,容易被追问细节后露馅;重点说清 LayoutTree 如何生成、ComputedStyle 怎么算、以及为什么 transform 比 top 快——这些才是现在真正在跑的逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











