总是记不清的重排/回流(reflow)和重绘(repaint)

重排会导致重绘,重绘不会导致重排 。

中文环境下面的 重排 会有另外一种称呼方式叫做 回流。以前一直不理解为什么重排叫回流(直译的 reflow),导致我在记忆的过程中我总是会把他们混在一起,分不清回流是重排还是重绘。

他们对应的含义我倒是分的还是比较清楚的。简单来说就是,牵扯页面布局的页面更新是重排,重绘就只是一些不影响布局的样式更新……

💥 触发机制

重排的触发机制我归类为以下三类:

  • 视窗大小发生改变;
  • DOM的操作(可见元素);
  • 元素几何样式和定位方式被改变;
  • 部分获取元素属性和API的调用;

视窗大小发生改变DOM的操作 都很容易理解,可视区域的改变、DOM元素的增/删/改都会触发重排。

需要注意的是 元素几何样式的改变获取元素属性和API的调用 这两块。

1. 元素几何样式的改变

元素宽高和位置这些属性的变更肯定会触发重排,但是修改字体字号也是会触发重排的。因为会改变容器的宽高,从而影响到页面布局。

2. 部分获取元素属性和API的调用

分为两类,一类是访问特定属性,比如说获取元素的盒模型信息。
一类是API的访问,例如 getClientRects()scrollTo()、getComputedStyle() 这类API,它们会访问某个元素尺寸和定位的属性,为了保证拿到的是精确值,不得不提前触发一次重排。

更详细的可以阅读 精读《web reflow》 这篇文章。

当然也不是每次访问元素位置都会触发 reflow,在浏览器触发 reflow 后,所有已有元素位置都会记录快照,只要不再触发位置等变化,第二次开始访问位置就不会触发 reflow
精读《web reflow》


🎨 关于重绘的部分

关于重绘我认为其实就是影响布局的样式修改的元素外观更新,都可以认为是重绘。但是有部分会影响到元素位置/宽高的变更、显示/隐藏的CSS属性并不会触发重排。比如说:

  • 使用 transform 属性使元素平移、形变等变换;
  • 使用 visibleopacity 属性显示/隐藏元素;

甚至有一部分的属性可以使直接跳过重排重绘的步骤,直接进入合成(Composite)阶段,还有关于重排重绘的优化我就不过多赘述了,感兴趣可以直接查看 《你真的了解回流和重绘吗》 这篇文章。


🧐 一些疑问

使用 absolutefixed 脱离文档流后,修改元素定位等原来会触发重排属性还会触发重排吗?

会,但是因为不会影响父级和兄弟元素的定位,所以它的重排会非常的快。但是使用 float 来脱离文档流还使其它元素内的文本进行环绕,所以可能会发生大规模重排。具体可以参看这篇问答 修改浮动元素宽高之后是否会触发重排?

相关文档

Rendering: repaint, reflow/relayout, restyle / Stoyan’s phpied.com
weekly/242.精读《web reflow》 · ascoders/weekly
weekly/221.精读《深入了解现代浏览器三》 · ascoders/weekly
渲染流水线:CSS如何影响首次加载时的白屏时间?| 浏览器工作原理与实践
分层和合成机制:为什么CSS动画比JavaScript高效?| 浏览器工作原理与实践
HTML回流与重绘_ 空城机
介绍回流与重绘(Reflow & Repaint),以及如何进行优化? - 知乎
你真的了解回流和重绘吗 - 掘金
既不要重排也不要重绘,合成:transform如何实现动画效果? - 掘金