重排和重绘

2021/9/6 HTML
  • 重排(Reflow):当浏览器发现元素的几何属性(如位置、大小、布局等)发生变化时,需要重新计算元素在页面中的位置和大小,并更新整个页面的布局,这个过程称为重排,也叫回流。
  • 重绘(Repaint):当元素的外观发生变化,但不影响其在页面中的布局时,浏览器只需要重新绘制该元素,这个过程称为重绘。例如,改变元素的颜色、背景色、边框样式等,只会触发重绘。重排一定会触发重绘。

# 何时发生重排重绘

改变页面元素的大小、位置、是否隐藏都会触发重排:

  • 页面首次渲染。

  • 浏览器窗口大小发生改变。

  • 元素尺寸或位置发生改变元素内容变化(文字数量或图片大小等等)。

  • 元素字体大小、字体样式变化。

  • 添加或者删除可见的DOM元素。

  • 激活CSS伪类(例如:hover)。

  • 一些常用且会导致回流的属性和方法,因为这些都要去计算位置或大小:

    原因:浏览器为了避免连续多次操作导致布局树的修改重复计算位置信息,会合并这些操作,因此改动属性造成的reflow是异步的,如果此时使用JS获取布局属性,浏览器会直接reflow以便获取到最新位置信息。

    • clientWidth
    • clientHeight
    • clientTop
    • clientLeft
    • offsetWidth
    • offsetHeight
    • offsetTop
    • offsetLeft
    • scrollWidth
    • scrollHeight
    • scrollTop
    • scrollLeft
    • scrollIntoView()
    • scrollIntoViewIfNeeded()
    • scrollTo()
    • getComputedStyle()
    • getBoundingClientRect()

改变外观、风格不影响布局,则触发重绘:

  • 修改颜色color
  • 修改边框样式、背景颜色、背景图片。
  • 文字对齐方式text-decoration
  • outline(即使改变粗细也不会重排)。

# 减少回流和重绘

  • 最小化重绘和重排

    由于重绘和重排可能代价比较昂贵,因此最好就是可以减少它的发生次数。为了减少发生次数,我们可以合并多次对DOM和样式的修改,然后一次处理掉。

    const el = document.getElementById('test');
    el.style.padding = '5px';
    el.style.borderLeft = '1px';
    el.style.borderRight = '2px';
    // 大部分现代浏览器都对其做了优化,因此,只会触发一次重排。
    
    // 使用cssText
    el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
    // 修改CSS的class
    el.className += ' active';
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • 批量修改DOM

    当我们需要对DOM对一系列修改的时候,可以通过以下步骤减少回流重绘次数:

    • 使元素脱离文档流 => 对其进行多次修改 => 将元素带回到文档中。

    该过程的第一步和第三步可能会引起回流,但是经过第一步之后,对DOM的所有修改都不会引起回流,因为它已经不在渲染树了。

    有三种方式可以让DOM脱离文档流:

    • 隐藏元素,应用修改,重新显示。
    • 使用文档片段(document fragment,document.createDocumentFragment)在当前DOM之外构建一个子树,再把它拷贝回文档。
    • 将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素。
  • 避免触发同步布局事件

    访问元素的一些属性的时候,会导致浏览器强制清空队列,进行强制同步布局。

  • 对于复杂动画效果,使用绝对定位让其脱离文档流

    对于复杂动画效果,由于会经常的引起回流重绘,因此,我们可以使用绝对定位,让它脱离文档流。否则会引起父元素以及后续元素频繁的回流。

  • css3硬件加速(GPU加速)

    • 使用css3硬件加速,可以让transformopacityfilters这些动画不会引起回流重绘。
    • 对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。

    css3硬件加速的坑

    • 如果你为太多元素使用css3硬件加速,会导致内存占用较大,会有性能问题。
    • 在GPU渲染字体会导致抗锯齿无效。这是因为GPU和CPU的算法不同。可能CSS3的动画会产生字体模糊。

    常见的触发硬件加速的css属性(最好用transformanimations):

    • transform
    • animations
    • transition
    • opacity
    • filters
    • will-change

参考文章:你真的了解回流和重绘吗 (opens new window)

最近更新: 2025年03月19日 13:31:15