重绘(Repaint)和重排(Reflow)是浏览器渲染过程中的两个重要概念,它们对性能的影响不同。
浏览器渲染流程
HTML → DOM Tree
CSS → CSSOM Tree
↓
Render Tree → Layout(重排) → Paint(重绘) → Composite(合成)
重排(Reflow/Layout)
定义
重排是指浏览器重新计算元素的几何属性(位置、大小)的过程。
触发重排的属性
/* 盒模型相关 */
width, height, padding, margin, border
/* 定位相关 */
position, top, left, right, bottom
/* 浮动和清除 */
float, clear
/* 显示类型 */
display
/* 字体相关 */
font-size, font-family, font-weight
/* 文本相关 */
line-height, text-align, vertical-align, white-space
/* 溢出相关 */
overflow, overflow-x, overflow-y触发重排的操作
// 获取布局信息
element.offsetWidth
element.offsetHeight
element.offsetTop
element.offsetLeft
element.clientWidth
element.clientHeight
element.scrollWidth
element.scrollHeight
element.scrollTop
element.scrollLeft
// 获取计算样式
window.getComputedStyle(element)
element.getBoundingClientRect()
// DOM操作
element.appendChild(newElement)
element.removeChild(element)
element.innerHTML = 'new content'
// 样式修改
element.style.width = '100px'
element.style.height = '200px'重绘(Repaint)
定义
重绘是指浏览器重新绘制元素外观的过程,不涉及几何属性的改变。
只触发重绘的属性
/* 颜色相关 */
color, background-color, background-image
/* 边框样式 */
border-style, border-radius
/* 阴影效果 */
box-shadow, text-shadow
/* 轮廓 */
outline, outline-color, outline-style, outline-width
/* 可见性 */
visibility性能对比
| 操作类型 | 重排 | 重绘 | 合成 | 性能影响 |
|---|---|---|---|---|
| 修改width/height | ✅ | ✅ | ✅ | 最高 |
| 修改color | ❌ | ✅ | ✅ | 中等 |
| 修改transform | ❌ | ❌ | ✅ | 最低 |
实际示例对比
触发重排的操作
// 坏的做法 - 触发多次重排
function badResize() {
const element = document.querySelector('.box');
element.style.width = '200px'; // 重排 + 重绘
element.style.height = '200px'; // 重排 + 重绘
element.style.margin = '10px'; // 重排 + 重绘
// 每次都会触发重排
console.log(element.offsetWidth); // 强制重排
console.log(element.offsetHeight); // 强制重排
}只触发重绘的操作
function repaintOnly() {
const element = document.querySelector('.box');
element.style.color = 'red'; // 只重绘
element.style.backgroundColor = 'blue'; // 只重绘
element.style.boxShadow = '2px 2px 4px #000'; // 只重绘
}只触发合成的操作
function compositeOnly() {
const element = document.querySelector('.box');
element.style.transform = 'translateX(100px)'; // 只合成
element.style.opacity = '0.5'; // 只合成
}最佳实践总结
- 避免频繁读取布局属性
- 批量修改样式,使用CSS类或cssText
- 使用transform和opacity进行动画
- 合理使用will-change属性
- 使用文档片段进行批量DOM操作
- 避免在循环中修改样式
- 缓存布局信息,避免重复计算
理解重绘和重排的区别,有助于编写更高性能的前端代码,提升用户体验。