# 重排与重绘
当元素的样式发生变化时,浏览器需要触发更新,重新绘制元素。这个过程中,有两种类型的操作,即重绘与重排
# 重排(reflow)
当元素的尺寸、结构或触发某些属性时,浏览器会重新渲染页面,称之为 重排,此时,浏览器需要重新经过计算,计算后还需要重新布局页面,所以是比较重的操作
会触发重排的操作:
- 页面首次渲染
- 浏览器窗口大小改变
- 元素尺寸、位置、内容发生改变
- 元素字体大小变化
- 添加或删除可见的 dom 元素
- 激活 CSS 伪类(例如:hover)
- 查询某些属性或调用某些方法
- clientWidth、clientHeight、clientTop、clientLeft
- offsetWidth、offsetHeight、offsetTop、offsetLeft
- scrollWidth、scrollHeight、scrollTop、scrollLeft
- getComputedStyle()
- getBoundingClientRect()
- scrollTo
# 重绘(repaint)
当元素样式的改变不影响布局时,浏览器会使用重绘对元素进行升级,由于此时只需要 UI 层面的重新像素绘制,因此损耗较小
# 如何避免触发重排和重绘
重排必会触发重绘,重绘不一定触发重排。重排代价较高,重绘开销较小
CSS
- 避免使用 table 布局
- 尽可能在 DOM 树的最末端改变 class
- 避免使用多层内联样式
- 避免使用 CSS 表达式(如:calc())
- 将动画效果应用到 position 属性为 absolute 或 fixed 的元素上
- CSS3 硬件加速(GPU 加速)
javascript
- 避免频繁操作样式,可以汇总后统一 一次修改
- 尽量使用 class 进行样式修改
- 减少 dom 的增删次数,可以使用字符串或者 documentFragment 一次性插入
- 极限优化时,可以将其样式修改为
display: none
后修改 - 避免多次触发上面提到的那些会触发重排的方法,尽量用 变量存储
- 对具有复杂动画的元素使用绝对定位,使其脱离文档流,否则会引起父元素及后续元素频繁回流