重绘 vs 回流

4 阅读2分钟

核心概念

   
  ┌──────────┬────────────────────────────┬────────────────────────────┐                                                                                                               
  │          │       回流(Reflow)       │      重绘(Repaint)       │                                                                                                               
  ├──────────┼────────────────────────────┼────────────────────────────┤                                                                                                               
  │ 触发     │ 几何属性变化(宽高、位置) │ 外观属性变化(颜色、背景) │                                                                                                               
  ├──────────┼────────────────────────────┼────────────────────────────┤
  │ 流程     │ LayoutPaintCompositePaintComposite          │                                                                                                               
  ├──────────┼────────────────────────────┼────────────────────────────┤                                                                                                               
  │ 性能代价 │ 高                         │ 中                         │                                                                                                               
  ├──────────┼────────────────────────────┼────────────────────────────┤                                                                                                               
  │ 包含关系 │ 必定引起重绘               │ 不一定引起回流             │                                                                                                               
  └──────────┴────────────────────────────┴────────────────────────────┘                                                                                                               
   
  ---                                                                                                                                                                                  
  性能排序                                                                                                                                                                             

  合成(Composite)< 重绘(Repaint)< 回流(Reflow)
                                                                                                                                                                                       
  ---

查看分析

查看网页重绘(Repaint)和回流(Reflow)

  方法 1Chrome DevTools - Rendering 面板(最直观)

  1. 打开 DevToolsF12Cmd+Option+I)
  2. 右上角三点 → More tools → Rendering
  3. 勾选以下选项:

  ┌──────────────────────┬────────────────────────────┐
  │         选项         │            作用            │
  ├──────────────────────┼────────────────────────────┤
  │ Paint flashing       │ 绿色高亮显示发生重绘的区域 │
  ├──────────────────────┼────────────────────────────┤
  │ Layout Shift Regions │ 蓝色高亮显示发生回流的区域 │
  └──────────────────────┴────────────────────────────┘

  ---
  方法 2Performance 面板(精确分析)

  1. DevToolsPerformance 标签
  2. 点击录制 → 操作页面 → 停止
  3. 在火焰图中查找:
    - Layout = 回流(紫色)
    - Paint = 重绘(绿色)
    - Composite = 合成层

  点击具体的 Layout/Paint 事件可看到触发原因和耗时。

  ---
  方法 3Console 监听强制回流

  // 访问以下属性会强制触发回流
  const height = element.offsetHeight  // 在 Performance 里会体现

  ---
  方法 4Layers 面板(查看合成层)

  DevToolsMore tools → Layers

  可以看到哪些元素被提升为独立合成层(will-change、transform 等),合成层内的变化只触发 Composite,不触发重绘/回流。

  ---
  快速判断规则

  修改几何属性(宽高/位置/margin)→ 回流 + 重绘(最贵)
  修改外观属性(颜色/背景)       → 只重绘
  修改 transform/opacity          → 只合成(最便宜)

解决方案


  浏览器渲染流程

  DOM + CSSOMLayout(布局)→ Paint(绘制)→ Composite(合成)

  ---
  回流(Reflow)

  触发条件:改变了元素的几何属性,需要重新计算布局

  /* 这些会触发回流 */
  width / height / margin / padding
  position / top / left
  font-size / display
  添加/删除 DOM 节点

  执行步骤:LayoutPaintComposite(三步全走)

  ---
  重绘(Repaint)

  触发条件:外观改变,但不影响布局

  /* 这些只触发重绘 */
  color / background-color
  border-color / box-shadow
  visibility / outline

  执行步骤:PaintComposite(跳过 Layout)

  ---
  哪个更影响性能?

  回流 >> 重绘

  ┌──────────┬───────────────────────────────┬──────────────────────┐
  │          │             回流              │         重绘         │
  ├──────────┼───────────────────────────────┼──────────────────────┤
  │ 代价     │ 高(重新计算整个/局部布局树) │ 中(只重新像素填充) │
  ├──────────┼───────────────────────────────┼──────────────────────┤
  │ 影响范围 │ 可能影响整个页面              │ 仅影响自身区域       │
  ├──────────┼───────────────────────────────┼──────────────────────┤
  │ 包含关系 │ 回流必定引起重绘              │ 重绘不一定回流       │
  └──────────┴───────────────────────────────┴──────────────────────┘

  ---
  最优解:只触发合成

  /* 用 transform 代替 top/left */
  transform: translateX(100px);  /* 只合成,不回流不重绘 ✅ */
  left: 100px;                   /* 回流 + 重绘 ❌ */

  /* 用 opacity 代替 visibility */
  opacity: 0;      /* 只合成 ✅ */
  visibility: hidden; /* 重绘 ❌ */

  transform 和 opacity 的动画由 GPU 处理,完全绕过 LayoutPaint,性能最好。