核心概念:DOM 树 vs 渲染树

浏览器的渲染过程是「完整解析 DOM 树,但有选择地渲染可见内容」。理解这两者的区别至关重要。

💡 核心理念

浏览器「心里有数」(完整 DOM 树),但「只做有用的」(选择性渲染可见内容)

对比说明

特性 DOM 树 渲染树
包含内容 所有 HTML 元素,包括 display:none、script、link、meta 等 只包含可见元素
目的 JS 操作和动态变化的基础 布局和绘制的基础
生成时机 HTML 解析时立即构建 DOM 树 + CSSOM 树结合后生成
结构 与 HTML 结构完全对应 包含样式信息,与 DOM 不同

渲染流程总览

浏览器将 HTML/CSS/JS 转换为屏幕像素的完整流程包含以下步骤:

1. HTML 解析 → DOM 树
2. CSS 解析 → CSSOM 树
3. DOM + CSSOM → 渲染树
4. 布局(Layout)
5. 绘制(Paint)
6. 合成(Composite)→ 屏幕

哪些元素被排除在渲染树之外?

排除类型 说明 示例 影响
display: none 完全从渲染树移除 <div style="display:none"> 不占空间,触发重排
非视觉元素 没有视觉表现 <script>, <link>, <meta> 不影响渲染
visibility: hidden 在渲染树中,但不绘制 <div style="visibility:hidden"> 占空间,不触发重排
完全遮挡的元素 可能被优化跳过绘制 被不透明元素覆盖 仍在渲染树,布局需要

渲染树可视化示例

HTML 结构:

<div class="container"> <div class="visible">我是可见的</div> <div class="hidden" style="display: none;">我是 display: none 的</div> <div class="invisible" style="visibility: hidden;">我是 visibility: hidden 的</div> <script>console.log('我是 script')</script> </div>

DOM 树(完整):

div.container
div.visible div.hidden div.invisible script

渲染树(选择性):

div.container
div.visible div.invisible div.hidden script

渲染三阶段:布局 → 绘制 → 合成

📐

布局(Layout)

计算渲染树中元素的几何信息(宽、高、位置)

🎨

绘制(Paint)

将元素绘制成像素,填充颜色、文本、边框等

🖥️

合成(Composite)

将多个层合成到屏幕上,利用 GPU 加速

各阶段优化策略

阶段 优化策略 说明
布局 增量布局 只重新布局变化的元素
视口外延迟布局 滚动到附近时再计算
绘制 分层绘制 每层独立绘制,最后合成
增量绘制 只重绘变化的层
合成 GPU 加速 利用 GPU 处理层合成
跳过遮挡层 被完全遮挡的层跳过合成

浏览器优化层次图

🚀 合成层(GPU 加速) 最快
🎨 绘制层(分层绘制)
📐 布局层(增量布局)
🌳 渲染树构建 基础

💡 性能优化建议

使用 transformopacity 动画可触发 GPU 加速,避免重排重绘。

display: none vs visibility: hidden

特性 display: none visibility: hidden
渲染树 ❌ 移除 ✅ 保留
占空间 ❌ 不占 ✅ 占空间
触发重排 ✅ 是 ❌ 否
触发重绘 ✅ 是 ✅ 是
可继承 ❌ 否(子元素也不显示) ✅ 是(子元素可覆盖)
屏幕阅读器 ❌ 不读 ❌ 不读

触发 GPU 加速的 CSS 属性

使用以下属性可触发 GPU 加速,提升动画性能:

属性 说明 性能
transform 2D/3D 变换 ⭐⭐⭐⭐⭐
opacity 透明度变化 ⭐⭐⭐⭐⭐
filter 滤镜效果 ⭐⭐⭐⭐
will-change 提前告知浏览器 ⭐⭐⭐⭐
content-visibility 视口外跳过渲染 ⭐⭐⭐⭐⭐
/* 优化动画示例 */ .animated-element { /* 触发 GPU 加速 */ transform: translateZ(0); will-change: transform, opacity; /* 视口外跳过渲染(Chrome 85+)*/ content-visibility: auto; contain-intrinsic-size: 300px; }

总结

📄 DOM 树:完整解析,一个都不能少
🎨 渲染树:有选择,只包含可见元素
📐 布局/绘制/合成:进一步优化,只处理可见内容
🖥️ 利用增量更新、分层绘制、GPU 加速提升性能

🎯 关键要点

浏览器 「心里有数」(完整 DOM 树),但「只做有用的」(选择性渲染可见内容)