reflow 也译为重排

浏览器渲染流程

未命名文件.jpg

reflow 回流 / 重排

  • 从图中可以看出,页面至少经历一次reflow(除非是完全空白的页面),也就是初始化的时候
  • 触发:对 DOM 操作导致 DOM 尺寸等属性的变化(比如修改元素的 widthheighttop)时,浏览器需要重新计算元素的属性,然后再将计算的结果绘制出来,这个过程叫做回流。
  • 常见的会引起回流的操作有:
    • 页面首次加载
    • 浏览器窗口尺寸改变
    • 元素尺寸或位置改变
    • 元素内容变化
    • 元素字体大小变化
    • 增删 DOM 元素
    • 查询或调用某些特定属性方法(为了确保数据的准确性)
      • offsetTop、offsetLeft、offsetWidth、offsetHeight
      • scrollTop、scrollLeft、scrollWidth、scrollHeight
      • clientTop、clientLeft、clientWidth、clientHeight
      • width、height
      • getComputedStyle()
      • getBoundingClientRect()

repaint 重绘

  • 触发:对 DOM 操作简单修改样式(比如修改元素的 visibilitycolorbackground-color 等)、却并未影响页面布局时,浏览器不需重新计算元素的位置尺寸等,直接为该元素绘制新的样式。


两者关系

  • reflow 必定引起 repaint,但 repaint 不会导致 reflow
  • reflow 比 repaint 的代价大

现代浏览器对性能的优化(浏览器层面)

因为频繁修改 DOMCSSOM 本身是件特别耗费性能的事情,现代浏览器大多对于都做了一定的优化。比如会把一系列的操作放进队列机制来批量更新布局,至少一个浏览器刷新帧 16ms(即大多数显示屏幕的刷新率为 60Hz,一个刷新间隔为 1000ms/60)才会清空队列(节流优化~)。
但在获取布局尺寸等信息的时候,为了保证数据的准确性,队列中无论有没有会影响这些属性或方法返回值的操作,浏览器也会强制清空队列,触发回流与重绘。( IE 不保证有这些优化)

  • offsetTopoffsetLeftoffsetWidthoffsetHeight
  • scrollTopscrollLeftscrollWidthscrollHeight
  • clientTopclientLeftclientWidthclientHeight
  • widthheight
  • getComputedStyle()
  • getBoundingClientRect()

    代码中优化回流和重绘

  • 减少使用 CSS 表达式;

  • 使用 transform 替代 top
  • 离线操作 DOM:把元素脱离文档流,然后对元素进行修改,这样只会导致重绘,而不会造成回流。
    • display:none:临时把元素 脱离文档流,进行批量操作后再放回。这样只会有一次回流;
    • createDocumentFragment:创建文档片段,一次性把内容放进文档;
  • 尽可能在 DOM 树的最末端改变 class:减小回流的范围;
  • 将动画效果应用到 position 属性为 absolutefixed 的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流;
  • JS 避免频繁读取会引发回流/重绘的属性:如果需要频繁使用,可以用变量把它缓存下来。

参考文章:

浅谈浏览器渲染、回流和重绘 【干货】十分钟读懂浏览器渲染流程