重绘和重排

1. 重绘

重绘(repaint 或redraw):当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上。

重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。

触发重绘的条件:改变元素外观属性。如:color,background-color,visibility,border-style,background,text-decoration,background-image,background-position,background-repeat,outline-color,outline,outline-style 等。

注意:table 及其内部元素可能需要多次计算才能确定好其在渲染树中节点的属性值,比同等元素要多花两倍时间,这就是我们尽量避免使用table 布局页面的原因之一。

2. 重排

重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。

width,height,padding,margin,display,font-size,float,text-align,clear等 CSS 属性会触发重排。

3. 重绘和重排的关系

在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。所以,重排必定会引发重绘,但重绘不一定会引发重排。

4. 减少重排和重绘的方法

4.1 CSS中减少重排和重绘

  • 尽可能在 DOM 树的最末端改变 class
  • 避免设置多层内联样式
  • 动画效果应用到 position 属性为 absolute 或 fixed 的元素上
  • 避免使用 table 布局
  • 使用 css3 硬件加速,可以让 transform、opacity、filters 等动画效果不会引起回流重绘

4.2 js中减少重排和重绘

  • 避免使用 JS 一个样式修改完接着改下一个样式,最好一次性更改 CSS 样式,或者将样式列表定义为 class的名称
  • 避免频繁操作 DOM,使用文档片段创建一个子树,然后再拷贝到文档中
  • 先隐藏元素,进行修改后再显示该元素,因为 display:none 上的 DOM 操作不会引发回流和重绘
  • 避免循环读取 offsetLeft 等属性,在循环之前把它们存起来
  • 对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流