一、浏览器渲染过程?
二、什么是重绘?回流(重排)?
定义
- 重排:重新生成布局。当DOM 的变化影响了元素的几何属性(宽和高)--比如改变边框宽度或给段落增加文字导致行数增加--浏览器需要重新计算元素的几何属性,同样其他元素的几何属性和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为重排。
- 重绘:重新绘制。完成重排后,浏览器会重新绘制受影响的部分到屏幕中。这个过程称为重绘。
重排与重绘的关系
重排一定会导致重绘,重绘不一定导致重排。如果DOM变化不影响几何属性,元素的布局没有改变,则只发生一次重绘(不需要重排)。
哪些情况会发生重绘,回流?
---不同的条件下发生重排的范围及程度会不同 :
- 页面初始渲染
- 改变字体,改变元素尺寸(宽、高、内外边距、边框,改变元素位置等
各种情况:
- 设置 style 属性的值
- 激活 CSS 伪类,比如 :hover
- 操作 class 属性
- css3的某些属性
- 改变元素内容(文本或图片等或比如用户在input框中输入文字)
- 添加/删除可见DOM元素(注意:如果是删除本身就display:none的元素不会发生重排;visibility:hidden的元素显示或隐藏不影响重排)
- fixed定位的元素,在拖动滚动条的时候会一直回流
- 调整窗口大小(Resizing the window)
- 计算 offsetWidth 和 offsetHeight 属性
浏览器是聪明的,当对以下属性进行操作的时候:
包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。
浏览器不会马上操作它们,而是会先缓存在队列中,有一定时间顺序去执行这些操作,但是在这过程中我们需要去获取在该队列中的属性时,浏览器为取得正确的值就会触发重排。这样就使得浏览器的优化失效了。
所以,在多次使用这些值时应进行缓存。
三、如何减少重绘和回流(重排)
CSS中避免回流、重绘
- 尽可能在DOM树的最末端改变class
- 避免设置多层内联样式
- 动画效果应用到position属性为absolute或fixed的元素上
- 避免使用table布局
- 使用css3硬件加速,可以让transform、opacity、filters等动画效果不会引起回流重绘
JS操作避免回流、重绘
- 避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称
- 避免频繁操作DOM,使用文档片段创建一个子树,然后再拷贝到文档中
- 先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘
- 避免循环读取offsetLeft等属性,在循环之前把它们存起来
- 对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流