重绘(Repaint)、重排 / 回流(Reflow / Layout)

浏览器回流和重绘区别:

回流是元素布局发生变化,浏览器需要重新计算布局,性能开销较大;
重绘是元素外观变化,不影响布局,只需重新绘制,性能较好;
回流一定会触发重绘,而重绘不一定触发回流。

一、先理解浏览器渲染流程

浏览器(如 Google ChromeSafari)渲染页面流程:

HTML → DOM
CSS  → CSSOM
DOM + CSSOM → Render Tree
↓
Layout(回流 / 重排)
↓
Paint(重绘)
↓
Composite(合成)

流程图:

解析HTML
    ↓
解析CSS
    ↓
生成Render Tree
    ↓
回流 (Reflow)
    ↓
重绘 (Repaint)
    ↓
合成显示

二、什么是回流 / 重排(Reflow / Layout)

回流(Reflow)
元素的几何信息改变 时,浏览器需要重新计算布局

比如:

  • 宽度改变
  • 高度改变
  • 位置改变
  • 元素增加删除
  • 字体大小改变

都会触发 回流

例如:

div.style.width = "200px"

浏览器必须重新计算:

  • 这个元素位置
  • 兄弟元素位置
  • 父元素高度

所以:

👉 回流非常耗性能


三、什么是重绘(Repaint)

重绘(Repaint)
元素外观改变,但布局没变

例如:

div.style.color = "red"

只需要重新绘制颜色:

不需要计算布局

所以:

👉 重绘比回流性能好


四、回流 vs 重绘

类型 是否计算布局 性能
回流(Reflow) ✅ 需要
重绘(Repaint) ❌ 不需要 较快

五、回流一定会触发重绘

这是一个重要知识点:

👉 回流一定会触发重绘
👉 重绘不一定触发回流

关系:

回流 → 重绘
重绘 ≠ 回流

六、哪些操作会触发回流

非常重要(面试常问)

1、DOM结构变化

appendChild
removeChild

2、元素尺寸变化

width
height
margin
padding

3、字体变化

font-size
font-family

4、浏览器窗口变化 

window.resize

5、读取布局属性(非常重要)

这些代码会 强制回流

offsetWidth
offsetHeight
clientWidth
getBoundingClientRect()

例如:

div.style.width = "200px"

console.log(div.offsetWidth)

浏览器必须:

  1. 先回流
  2. 再返回宽度

这叫:

👉 强制同步回流(性能杀手)

 

七、性能优化(非常重要)

❌ 错误写法(多次回流)

div.style.width = "100px"
div.style.height = "200px"
div.style.margin = "20px"

会触发多次回流


✅ 正确写法(合并修改)

div.style.cssText = `
  width:100px;
  height:200px;
  margin:20px;
`

只回流一次

八、使用 class 优化

div.style.width = "100px"
div.style.height = "200px"

div.classList.add("active")

 


九、使用 DocumentFragment(高级优化)

const fragment = document.createDocumentFragment()

for(let i=0;i<100;i++){
  const div = document.createElement("div")
  fragment.appendChild(div)
}

document.body.appendChild(fragment)

👉 只触发一次回流

十、最强优化:使用 transform(非常重要)

这是一个浏览器渲染机制的问题,本质是:transform 不会改变元素的布局(Layout),只改变元素的绘制(Paint/Composite)

所以不会触发 回流(Reflow),只会触发 重绘(Repaint) 或 合成(Composite)。

 

这个元素只是视觉上移动了但它在布局中的位置没有变

  • 不影响其他元素位置
  • 不重新计算布局
  • 不触发回流

 

修改:

left
top
width
height

会触发回流 ❌

推荐:

transform: translate()
scale()
rotate()

例如:

transform: translateX(100px)

👉 不触发回流
👉 只触发合成层

性能最好 🚀


十一、GPU加速(高级知识)

transform: translateZ(0);

或:

will-change: transform;

浏览器(如 Blink 引擎)会开启 GPU 加速:

  • 创建合成层
  • GPU渲染

性能提升明显

 

也就是

会开启 GPU 加速(浏览器会:👉 把这个元素 单独交给 GPU 处理

变成:CPU 计算 → GPU 合成 → 显示

这样动画就会 更流畅

 

posted @ 2026-04-21 11:36  SimoonJia  阅读(2)  评论(0)    收藏  举报