CSS回流和重绘是浏览器渲染页面的核心环节,二者的触发频率和范围直接决定了页面的渲染性能。理解二者的运行机制,是前端性能优化的基础工作。

什么是CSS回流和重绘
重绘
重绘指的是当元素的外观属性发生变化,但不影响其在文档流中的位置和布局时,浏览器重新绘制该元素的过程。常见触发重绘的属性包括color、background-color、visibility等。
回流
回流也叫重排,指的是当元素的布局属性发生变化,或者页面的整体布局需要重新计算时,浏览器重新计算所有元素的位置和尺寸,然后重新构建渲染树的过程。回流一定会触发重绘,但重绘不一定会触发回流。
触发回流和重绘的常见场景
- 修改元素的宽高、边距、定位等布局相关属性
- 读取
offsetWidth、offsetHeight、clientWidth等布局相关的属性值 - 添加或删除DOM节点
- 改变浏览器窗口的尺寸
- 修改元素的字体大小
- 激活CSS伪类比如
:hover
对性能的具体影响
重绘的性能开销相对较小,因为不需要重新计算布局,只需要重新绘制元素的外观。但如果短时间内触发大量重绘,比如循环修改元素的背景色,也会导致页面渲染卡顿。
回流的性能开销要大很多,因为回流会重新计算整个文档或者部分文档的布局,涉及到大量的计算工作。如果频繁触发回流,比如在一个动画中每一帧都修改元素的位置,会导致浏览器的计算压力骤增,页面帧率下降,出现明显的卡顿感。尤其是在DOM节点数量较多的复杂页面中,一次大规模回流可能耗时几十毫秒甚至上百毫秒,严重影响用户体验。
性能优化方案
减少回流次数
可以通过合并多次样式修改来减少回流,比如使用class一次性修改多个样式,而不是逐行修改属性。以下是两种修改方式的对比:
// 频繁触发回流的写法
const element = document.getElementById('test');
element.style.width = '100px';
element.style.height = '100px';
element.style.margin = '10px';
// 优化后的写法,只触发一次回流
const element = document.getElementById('test');
element.classList.add('new-style');
避免强制同步布局
不要在修改样式之后立刻读取布局相关的属性,因为这会强制浏览器提前执行回流计算。可以将读取操作放在所有修改操作之前,或者缓存属性值。
// 强制同步布局的写法,每次读取都会触发回流
const element = document.getElementById('test');
element.style.width = '200px';
const width = element.offsetWidth; // 触发回流
element.style.height = width + 'px';
const height = element.offsetHeight; // 再次触发回流
// 优化后的写法,只触发一次回流
const element = document.getElementById('test');
const width = element.offsetWidth; // 先读取缓存值
const height = element.offsetHeight;
element.style.width = '200px';
element.style.height = height + 'px';
使用脱离文档流的元素做动画
对于需要频繁修改位置的动画,可以使用position: absolute或者position: fixed让元素脱离文档流,这样元素的变化只会触发自身的回流,不会影响其他元素的布局。
批量操作DOM
需要多次修改DOM时,可以先将元素脱离文档流,修改完成后再插回文档。比如使用documentFragment批量创建节点,或者先设置元素display: none,修改完成后再显示。
// 使用documentFragment批量插入节点,只触发一次回流
const fragment = document.createDocumentFragment();
for (let i = 0; i < 10; i++) {
const li = document.createElement('li');
li.textContent = '列表项' + i;
fragment.appendChild(li);
}
document.getElementById('list').appendChild(fragment);
总结
CSS回流和重绘的性能影响不容忽视,开发者在编写代码时需要时刻注意避免不必要的触发。通过合理的样式修改方式、DOM操作逻辑和动画实现方案,可以有效减少回流和重绘的次数,提升页面的渲染性能。在复杂项目中,还可以结合浏览器的性能分析工具,定位频繁触发回流重绘的代码位置,针对性进行优化。