基本概念

回流(Reflow) 和 重绘(Repaint) 是浏览器渲染过程中的两个重要概念,它们会影响页面性能。

回流(Reflow)

  • 也称为"布局"(Layout)

  • 当渲染树中的一部分或全部因为元素的规模尺寸、布局、隐藏等改变而需要重新构建时发生

  • 会计算所有受影响元素的几何属性(位置和大小)

  • 是开销较大的操作

重绘(Repaint)

  • 当元素的外观样式改变但不影响布局时发生(如颜色、背景色等)

  • 不需要重新计算几何属性

  • 开销相对较小

触发条件

触发回流的操作

  • 页面首次渲染

  • 浏览器窗口大小改变

  • 元素尺寸或位置改变(width, height, margin, padding, border等)

  • 元素内容变化(文字数量、图片大小等)

  • 添加/删除可见DOM元素

  • 激活CSS伪类(:hover等)

  • 查询某些属性或调用某些方法(见下文)

触发重绘的操作

  • 颜色、背景色等不影响布局的样式变化

  • visibility样式的改变(但display:none会触发回流)

性能影响

回流比重绘的代价更高,因为它会导致浏览器重新计算所有受影响元素的几何属性,并可能导致部分或整个渲染树需要重新构建。

优化建议

  1. 避免频繁操作样式:最好一次性修改样式,而不是多次修改

    // 不好
    el.style.margin = '5px';
    el.style.padding = '10px';
    
    // 更好
    el.style.cssText = 'margin:5px; padding:10px;';
  2. 使用文档片段(DocumentFragment):批量操作DOM

    const fragment = document.createDocumentFragment();
    // 添加多个元素到fragment
    document.body.appendChild(fragment);
  3. 避免强制同步布局:不要在读取布局属性前修改样式

    // 不好 - 强制同步布局
    const width = el.offsetWidth;
    el.style.width = width + 10 + 'px';
    
    // 更好 - 先修改后读取
    el.style.width = '100px';
    const width = el.offsetWidth;
  4. 使用transform和opacity:这些属性不会触发回流

  5. 避免table布局:table中一个小改动可能导致整个table回流

  6. CSS优化

    • 避免多层内联样式

    • 将动画元素设置为position: absolute/fixed

    • 避免CSS表达式

常见触发回流的属性和方法

属性(读取时会强制回流)

  • offsetTop/offsetLeft/offsetWidth/offsetHeight

  • scrollTop/scrollLeft/scrollWidth/scrollHeight

  • clientTop/clientLeft/clientWidth/clientHeight

  • getComputedStyle()

  • getBoundingClientRect()

方法(可能触发回流)

  • elem.append()

  • elem.remove()

  • elem.insertBefore()

  • elem.replaceChild()

  • elem.style.setProperty()

  • window.getComputedStyle()

  • elem.scrollIntoView()

  • elem.focus()

理解回流和重绘有助于开发者编写更高效的CSS和JavaScript代码,提升页面性能。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐