重绘(repaint或redraw):当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上。重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
触发重绘的条件:改变元素外观属性。如:color,background-color等。
注意:table及其内部元素可能需要多次计算才能确定好其在渲染树中节点的属性值,比同等元素要多花两倍时间,这就是我们尽量避免使用table布局页面的原因之一。
重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
重绘和重排的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。所以,重排必定会引发重绘,但重绘不一定会引发重排。
常见引发回流的操作:
- 调整窗口大小
- 改变字体大小
- 样式表变动
- 元素内容变化,尤其是输入控件
- CSS伪类激活
- DOM操作
- offsetWidth, width, clientWidth, scrollTop/scrollHeight的计算, 会使浏览器将渐进回流队列Flush,立即执行回流。
如何减少重绘和回流
避免大量页面回流的手段也有很多,其本质都是尽量减少引起回流和重绘的DOM操作:
- 避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
-
避免循环操作DOM。创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document。
也可以在一个display:none的元素上进行操作,最终把它显示出来。因为display:none上的DOM操作不会引发回流和重绘。
-
避免循环读取offsetLeft等属性。在循环之前把它们存起来。
-
绝对定位具有复杂动画的元素。绝对定位使它脱离文档流,否则会引起父元素及后续元素大量的回流。
使用CSS3的transition也可以获得不错的性能。