重绘和重排
2025/11/13大约 1 分钟
重绘和重排
浏览器渲染流程
┌────────────────────────────────────────────┐
│ 浏览器渲染流程 │
│ │
│ JS/CSS → Layout(重排) → Paint(重绘) │
│ ↓ │
│ 几何属性变化 样式变化 │
│ (位置/尺寸/显隐) (颜色/阴影/背景) │
└────────────────────────────────────────────┘重排
几何属性改变,布局需要重新计算
触发重拍
// 几乎所有改变布局的操作
element.style.width = "200px"; // 尺寸
element.style.height = "100px"; // 尺寸
element.style.padding = "20px"; // 内边距
element.style.margin = "10px"; // 外边距
element.style.display = "none"; // 显示/隐藏
element.style.fontSize = "16px"; // 字体大小
window.resize(); // 窗口大小改变
scrollTo(0, 100); // 滚动
// 添加/删除元素
document.body.appendChild(child);
// 获取布局信息(强制同步重排)
const width = element.offsetWidth; // ⚠️ 常见性能陷阱
const height = element.scrollHeight;
const top = element.getBoundingClientRect().top;重绘
外观改变不影响布局, 只需要重新绘制
触发重绘
主要是改变颜色和透明度之类的,不影响结构和布局
// 只改变外观,不影响布局
element.style.backgroundColor = 'red' // 背景色
element.style.color = 'blue' // 文字颜色
element.style.borderColor = 'green' // 边框色
element.style.visibility = 'hidden' // 隐藏但占位
element.style.opacity = '0.5' // 透明度(现代浏览器优化)
element.style.boxShadow = '0 0 5px black' // 阴影性能影响
重排代价分析:
轻度重排(局部) ████░░░░░░ 约 1-3ms
重度重排(全页) ██████████ 约 100-400ms
重绘代价分析:
简单重绘 ██░░░░░░░░ 约 0.5-1ms
复杂重绘 ████░░░░░░ 约 2-5ms危险操作
强制触发重排(读取offsetWidth)
for (let i = 0; i < 1000; i++) {
element.style.left = i + "px"; // 触发重排
console.log(element.offsetWidth); // 又触发重排(读布局)
}优化方式
- 批量读取 批量操作
document.createDocumentFragment - css 样式合并操作
// ❌ 多次修改
element.style.width = "100px";
element.style.height = "100px";
element.style.padding = "10px";
// ✅ 一次修改
element.style.cssText = "width: 100px; height: 100px; padding: 10px";
// ✅ 使用 class
element.classList.add("active");- 使用transform