🎨 当浏览器变成装修工:重绘与重排的爱恨情仇

175 阅读3分钟

🏠 故事开始:浏览器的装修日记

想象你正在装修房子:

  • 布局(Layout) = 设计图纸(确定家具位置和大小)
  • 重排(Reflow) = 突然决定把沙发从客厅搬到卧室(所有家具位置都要重新计算)
  • 重绘(Repaint) = 给墙壁换颜色(家具位置不变,只是表面刷新) 今天我们就通过 一些简单的代码,聊聊这两个让前端开发者又爱又恨的概念。

🚀 代码里的性能陷阱

反面教材:让CPU崩溃的JS动画

先看代码:

let width = 0;
function move() {
  width += 2;
  box.style.width = width + 'px'; // 每次修改都会触发重排
  if(width < 300) {
    requestAnimationFrame(move);
  }
}

重绘重排1.gif

这段代码通过不断修改 width 属性实现动画,就像你每分钟都要重新测量房间大小——浏览器会疯狂执行:

  1. 计算盒子新尺寸( 重排 )
  2. 重新绘制像素( 重绘 )
  3. 重复上述步骤...

优化尝试:CSS Transition的救赎

再看改进代码:

.box {
  transition: left 1s ease-out; /* 比JS动画更聪明 */
}
.box.active {
  left: 300px; /* 仍然会触发重排 */
}

重绘重排2.gif

虽然CSS过渡比JS动画高效,但修改 left 属性依然会触发重排。就像你虽然请了装修公司,但还是要天天改设计图。

💡 性能优化的黄金法则

我们一一来揭秘,其实浏览器有个隐藏福利:

transformopacity属性不会触发重排!

它们就像给元素开了VIP通道,直接交给GPU处理,跳过布局计算环节。把上面的代码改成这样:

.box.active {
  /* left: 300px; */ /* 👈 这是青铜玩家的做法 */
  transform: translateX(300px); /* 👑 这是王者操作 */
}

重绘重排3.gif

🕵️‍♂️ 如何检测重排和重绘?

  1. 打开 Chrome DevTools(开发者工具)。

    • 右键点击页面并选择  “检查” (Inspect),或者使用快捷键 Ctrl+Shift+I(Windows/Linux)或 Cmd+Opt+I(Mac)。
  2. 转到  “Performance”  面板。

    • 在DevTools界面顶部的标签中,选择 Performance 标签。
  3. 启用 Paint flashing

    • 在 Performance 面板中,点击右上角的 三个垂直点(更多选项),然后选择  “Settings”
    • 在设置面板中,找到  “Rendering”  部分,勾选  “Paint flashing”  选项。
  4. 启用 Layout Shift Regions

    • “Rendering” 同样找到 Layout Shift Regions,勾选上。
  5. 启用后,浏览器会在页面绘制时以闪烁的方式显示出每次重绘的区域,帮助你分析页面渲染的性能瓶颈。

勾选 Paint flashing(重绘区域会闪烁绿色)

勾选 Layout Shift Regions(重排区域会闪烁蓝色)

试试用这个方法对比 文章的第一段代码 和优化后的版本,你会看到明显差异!

三次结果分别对比

重绘重排6.gif

重绘重排5.gif

重绘重排4.gif

🛠️ 前端性能优化工具箱

  1. 批量DOM操作 :先离线修改DOM,再一次性更新
  2. 使用BFC :隔离布局影响(就像给房间装隔断)
  3. will-change: transform :提前告诉浏览器"我要动了!"
  4. 避免强制同步布局 :不要在读取offsetHeight后立即修改样式

总结:重绘重排防坑指南

Snipaste_2025-07-12_11-31-33.png

记住: 重排是性能杀手,重绘是帮凶,transform是你的超级英雄!

下次写动画时,想想浏览器这个装修工的苦衷——少改图纸(重排),多刷油漆(重绘),实在不行就用VIP通道(transform)!

💬 互动话题:你遇到过哪些因为重排导致的性能问题?评论区分享你的踩坑经历吧!