关于什么是重绘和重排,以及如何减少重绘和重排?
浏览器渲染页面的过程大致是:解析HTML生成DOM树 -> 解析CSS生成CSSOM树 -> 合并成Render Tree(渲染树) -> 布局(Layout) -> 绘制(Painting)。
重排 (Reflow)
当元素的几何属性(尺寸、位置、隐藏等)发生改变,浏览器需要重新计算元素在视口内的确切位置和大小,并重新构建渲染树。
注意: 重排一定会引起重绘,因为位置变了,自然要重新画。
重绘 (Repaint)
当元素的外观属性(颜色、背景、阴影等)发生改变,但不影响布局时,浏览器会将新样式重新绘制在屏幕上。
注意: 重绘不一定引起重排,因为布局没变
什么操作会触发它们?
触发重排(最耗性能)
- 页面首次渲染(不可避免)。
- 浏览器窗口大小改变(Resize)。
- 元素尺寸/位置变化:修改 width, height, margin, padding, border, top, left 等。
- 内容变化:输入框输入文字、图片加载成功导致尺寸撑开。
- DOM操作:添加、删除、移动DOM节点。
- 获取某些特定属性(会导致浏览器强制刷新队列以获取准确值):offsetTop, offsetLeft, offsetWidth, offsetHeightscrollTop, scrollLeft, scrollWidth, scrollHeightclientTop, clientLeft, clientWidth, clientHeightgetComputedStyle()
触发重绘
- color, background-color, visibility: hidden (注意不是 display: none)。
- border-style, outline, box-shadow
性能优化:
CSS 层面
- 使用 transform 代替 top/left:transform 会开启硬件加速,在合成层处理,不会触发重排。
- 使用 visibility 代替 display: none:前者只重绘,后者触发重排。
- 避免使用 table 布局:表格一个小改动可能导致整个 table 重新布局。
- 离层化处理:对频繁动画的元素使用 position: absolute 或 fixed,使其脱离文档流,减少对其他元素的影响