CSS的重绘和重排是什么?如何减少css的重绘和重排?
一.理解重排与重绘
要理解重排和重绘,需要先了解浏览器渲染步骤:构建DOM树、构建CSSOM树、合成渲染树、布局(Layout,即重排)、绘制(Paint,即重绘)。
重排 (Reflow / Layout)
当渲染树中元素的尺寸、布局、位置或内容发生改变,导致浏览器需要重新计算所有受影响元素的几何属性(位置和大小),并更新整个渲染树的过程,就是重排。重排的范围可能很大,从当前元素向上定位祖先,向下所有子节点都可能被波及。
触发重排的常见操作包括:改变窗口大小、更新元素内容、调整CSS盒模型相关属性(如宽度、高度、边距)、操作DOM(添加或删除可见元素)、读取某些属性(如
offsetTop
、clientHeight
等)。重绘 (Repaint)
当元素的样式发生改变,但不影响其布局(例如修改颜色、背景色、边框颜色、可见性
visibility
等),浏览器只需重新绘制元素的外观到屏幕,这个过程就是重绘。由于跳过了计算布局的阶段,重绘的性能开销通常远小于重排。
两者的核心关系是:重排必定会触发重绘,因为布局改变后外观需要更新;但重绘不一定触发重排,如果只是视觉变化而布局未变
。
二.🛠️ 优化策略与实用技巧
减少重排和重排的关键在于尽量减少对渲染树的干扰,并将不可避免的操作的影响降至最低。
合并DOM操作
避免逐条修改样式或频繁操作DOM。最有效的方法是集中修改:
使用
cssText
或classList
:一次性设置多个样式属性,或通过切换预定义的CSS类来批量改变样式。使用文档片段
DocumentFragment
:需要对DOM进行多次添加或删除时,先在内存中的DocumentFragment
上操作,最后一次性将片段添加到真实DOM中。
优化动画与变换
动画会频繁触发渲染,优化至关重要:
优先使用
transform
和opacity
:这两个属性实现的动画通常由合成层处理,跳过布局和绘制阶段,直接由GPU合成,效率极高。应用
position: absolute
或fixed
:为动画元素设置绝对或固定定位,可使其脱离普通文档流,动画变化时减少对其他元素的影响范围。使用
requestAnimationFrame
:而非setTimeout
或setInterval
来执行动画,确保动画回调在浏览器下一次重绘前执行,更流畅。
谨慎访问布局属性
在JavaScript中读取
offsetTop
、scrollHeight
、getComputedStyle()
等布局属性时,浏览器为返回精确值可能强制刷新渲染队列,导致同步重排。应在一次读取中缓存这些值,避免在循环或频繁调用的函数中重复读取。
优化CSS与选择器
避免过于复杂的选择器:特别是深层嵌套的选择器,会增加浏览器匹配样式的时间。
避免使用
table
布局:table
中某个小改动可能导致整个表格重排。减少使用可能高开销的属性:如
box-shadow
和filter
,尤其在多个元素上使用时。