浏览器幕后 01:从输入到像素(全景图)
本系列名为 《浏览器幕后:渲染流水线深度解构》。
第一篇我们先搭好全景图:浏览器从 HTML/CSS 到屏幕像素,到底分了哪几步?每一步解决什么问题?
1. 为啥要学渲染原理?—— 治“无效焦虑”
你已经会写 Flex、Grid、Position,能做出漂亮的页面。但有时候你会遇到这些“玄学”问题:
- 页面滚动卡顿,明明没几行代码
z-index: 9999就是不生效fixed元素突然跟着父容器跑了- 改一个
width,整个页面闪一下
这些都不是“CSS 的 bug”,而是你不了解浏览器在背后怎么计算。
渲染原理就是给你一张“排错地图”:问题出在哪一步,该怎么修,一目了然。
2. 一句话先记住:浏览器把代码变像素,只做 6 件事
| 步骤 | 英文名 | 大白话 |
|---|---|---|
| 1 | HTML → DOM | 读你的 HTML,搭出“元素树” |
| 2 | CSS → CSSOM | 读你的 CSS,搭出“样式规则树” |
| 3 | Style | 算出每个元素的最终样式(比如 width: 50% → 200px) |
| 4 | Layout | 算出每个元素的尺寸和坐标(比如卡片在 x=100, y=200) |
| 5 | Paint | 画背景、边框、文字(像画画一样填充像素) |
| 6 | Composite | 把多个图层叠在一起,交给屏幕显示 |
新手先记这 6 步名字即可,后面我会用例子帮你“看”到每一步。
3. 用一个真实卡片,带你“走一遍流程”
假设你有这么一段代码:
<div class="card">Hello</div>
.card {
width: 50%;
margin: 0 auto;
padding: 16px;
background: #fff;
border-radius: 8px;
}
浏览器做了这些事:
- DOM 树:发现一个
<div>,给它标记为“card”。 - CSSOM:找到
.card规则,记下width:50%、margin:0 auto等。 - 样式计算:父容器宽度 800px →
width最终 = 400px;margin: 0 auto算出左右 margin 各 200px。 - 布局:确定这个 div 的左上角坐标是 (200, 某个 y),宽度 400px,高度由内容+padding 撑开。
- 绘制:从 (200, y) 开始画一个白色圆角矩形,里面写黑色文字 “Hello”。
- 合成:如果页面还有其他图层(比如固定按钮),按顺序叠好后显示。
你看,一句 width:50% 背后是好几步数学计算。
理解了这些,你就知道为什么“改 width 可能导致整个页面重新布局(重排)”。
4. 你现阶段最该关注哪两步?—— Style 和 Layout
新手遇到的 80% 样式问题,都出在 样式计算 和 布局 阶段:
| 常见问题 | 归属阶段 | 解决方案方向 |
|---|---|---|
| 优先级混乱(为什么我的样式没生效) | Style | 学习选择器权重 |
absolute 元素跑飞 | Layout | 检查父元素 position: relative |
sticky 不生效 | Layout | 检查 top 值和父容器 overflow |
| 盒模型总宽度算错 | Layout | 确认 box-sizing |
fixed 元素相对父容器定位 | Layout | 检查祖先是否有 transform |
所以:先搞定 Style 和 Layout,你就能解决绝大多数布局痛点。
5. 重排 vs 重绘 —— 性能问题的根源
- 重排(Reflow):尺寸或位置变了,浏览器要重新计算布局(Layout 阶段)。开销大。
- 重绘(Repaint):外观变了(颜色、背景),但几何不变,只重新绘制(Paint 阶段)。开销小。
举例对比
| 操作 | 触发重排? | 触发重绘? |
|---|---|---|
改 width / height | ✅ | ✅ |
改 background-color | ❌ | ✅ |
改 transform(用 GPU 动画) | ❌ | ❌(只走合成) |
这就是为什么做动画推荐用
transform而不是left。
6. 5 分钟实验:亲眼看到重排和重绘的区别
打开 Chrome DevTools → Rendering 面板 → 勾选 Paint flashing(重绘闪烁)。
- 在页面上快速滚动,你会看到绿色闪烁(重绘)。
- 写一段脚本每帧改变
left,你会看到 Layout 相关指标飙升。
自己试试:把下面的代码复制到 console 执行,然后看 Performance 面板:
let left = 0;
setInterval(() => {
document.querySelector('.box').style.left = left++ + 'px';
}, 16);
然后换成 transform: translateX(),对比两者 Layout 耗时。
—— 这个实验能让你一辈子记住“为什么推荐 transform”。
7. 新手阅读这类文章的正确姿势(省力不劝退)
- 第一遍:只看每节的“结论”和“表格”,别管术语。
- 第二遍:带着问题“这一步解决了什么?”去读细节。
- 第三遍:打开 DevTools 做文章里的 5 分钟实验。
判断你是不是真的懂了,不是看你能背出 6 个步骤,而是问自己:
- 我的页面卡顿,是重排还是重绘引起的?
- 我改的这个属性,会影响 Layout 还是 Paint?
- 有没有更便宜的改法(比如
transform替代top/left)?
8. 系列预告 & 下次内容
本文是 《浏览器幕后:渲染流水线深度解构》系列的第一篇,后续你会看到:
- 02 - CSSOM 与样式计算:优先级、继承、值处理
- 03 - 视觉格式化模型与布局:包含块、BFC、边距折叠
- 04 - Flex/Grid 的布局算法思维:剩余空间分配、fr 原理
- 05 - 重排重绘与层叠上下文:性能优化 + z-index 真相
每个概念都会配上“大白话解释”+“可运行的最小示例”。
9. 写在最后:你不是在背概念,而是在建立“排错坐标系”
以前你遇到 fixed 失效,可能会搜一堆文章乱试。
学了渲染原理之后,你会自动想:
- 它是定位问题 → 先看包含块(有没有
transform祖先) - 它是层级问题 → 看层叠上下文(
z-index生效前提)
这就是“从瞎蒙到推理”的升级。
下一篇,我们正式进入样式计算的世界。
你遇到过最“玄学”的 CSS 问题是啥?评论区写出来,下一篇我可能拿它当案例。