重排(回流/布局):
- 定义:当HTML元素的几何(尺寸/位置)属性变化,导致浏览器重新计算布局的过程
- 触发:
- 修改尺寸(width/height)/位置(margin/padding)信息
- 调整窗口大小和设备方向变化
- 增删可见的dom
- 读取布局(offsetWidth / clineHeight)信息会强制同步重排(性能敏感)
- 影响:重排会触发重绘,会引发整个渲染树重新计算,开销大
重绘:
- 定义:元素外观(颜色,背景)变化,但不影响布局时,浏览器重新绘制受影响区域
- 触发:
- 颜色/背景/边框颜色(border-color)等样式
- 不涉及几何变化的css动画(opacity)
- 影响:开销比重排小,但还是应该尽量避免高频触发
页面渲染的过程:
- 流程:解析 -> 渲染树 -> 重排(回流/布局) -> 重绘(绘制) -> 合成
- 解析html
- 浏览器逐行解析html生成dom树
- 遇到script标签时会阻塞暂停解析,并执行JavaScript(除非script标签上注明属性 async/defer)
- 解析css
- 合并渲染树
- 将dom树和cssom树合并,生成渲染树 render tree
- 渲染树仅包含可见元素(display:none 排除);
- 布局
- 绘制
- 将渲染树转化为屏幕上的像素,包含文本,颜色等视觉样式部分
- 合成
如何优化页面渲染速度:
- 关键策略:
- 减少重排:
- 批量修改DOM: 使用 documentFragment 或 虚拟dom(React / vue)
- 避免逐行读取布局属性(先读取 后写入)
- 使用css transform 或 position: absolute / fixed 等脱离文档流
- 减少重绘:
- 使用css3动画(transform / opacity) 触发 GPU 加速(合成层)
- 将频繁变动的元素提升为合成层(will-change: transform)
如何查看页面的重排和重绘:
示例:
element.style.width = '100px';
element.style.height = '200px';
element.style.cssText = 'width: 100px; height: 200px;';
element.style.transform = 'translateX(100px)';