重排与重绘
重排和重绘是浏览器渲染过程中的两个关键阶段,理解它们对性能优化至关重要。
核心概念
重排(Reflow)
元素几何属性变化时,浏览器重新计算元素位置和大小。
触发重排的操作:
- 改变窗口大小
- 改变字体大小
- 增删 DOM 元素
- 改变元素尺寸(width、height、padding、margin、border)
- 改变元素位置(top、left、float、position)
CSS
/* 触发重排 */
.box {
width: 200px; /* 尺寸变化 */
height: 100px;
margin: 20px;
}
重绘(Repaint)
元素外观属性变化时,浏览器重新绘制元素外观(不影响布局)。
触发重绘的操作:
- 改变颜色(color、background-color)
- 改变边框颜色
- 改变透明度(opacity)
- 改变阴影(box-shadow)
- 改变可见性(visibility)
CSS
/* 触发重绘,不触发重排 */
.box {
color: red; /* 颜色变化 */
background-color: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
性能对比
| 操作类型 | 性能消耗 | 影响范围 |
|---|---|---|
| 重排 | 高 | 整体布局重新计算 |
| 重绘 | 中 | 仅重绘元素外观 |
| 合成层 | 低 | GPU 加速,性能最佳 |
优化策略
批量修改样式
CSS
/* 差:多次触发重排 */
.box { width: 100px; }
.box { height: 200px; }
.box { margin: 10px; }
/* 好:一次性修改 */
.box {
width: 100px;
height: 200px;
margin: 10px;
}
使用 transform 代替位置属性
CSS
/* 差:触发重排 */
.box {
position: absolute;
left: 100px;
top: 100px;
}
/* 好:仅触发合成层 */
.box {
transform: translate(100px, 100px);
}
使用 opacity 代替 visibility
CSS
/* 差:触发重绘 */
.box { visibility: hidden; }
/* 好:可能触发合成层 */
.box { opacity: 0; }
避免频繁读取布局属性
JavaScript
// 差:强制同步布局
const width = box.offsetWidth;
box.style.width = width + 100 + 'px';
// 好:批量读写分离
const width = box.offsetWidth;
// 先完成所有写操作
box.style.width = width + 100 + 'px';
box.style.height = '200px';
使用
transform和opacity做动画可跳过重排重绘,直接走合成层。
要点总结
- 重排代价高于重绘,尽量避免触发
- 批量修改样式,减少重排次数
- 使用 transform/opacity 代替位置/可见性属性
- 读写分离,避免强制同步布局
- 复杂动画元素可提升为合成层
📝 发现内容有误?点击此处直接编辑