Published on

重排重绘

Authors

浏览器的重绘重排,指的是当 DOM 和 CSSOM 被修改后,可能会重新触发浏览器渲染的关键路径布局绘制

  1. 重排:当 DOM 元素的变化影响了它的几何属性(大小,位置,布局),浏览器需要重新计算元素的几何属性,并重新构建文档树的全部或部分过程
  2. 重绘:当 DOM 元素属性的变化不影响它在文档流中的位置和大小时,浏览器需要重新绘制元素外观。 重排必定导致重绘,因为布局变化后需要重新绘制。而重绘不一定导致重排,因为布局可能未发生变化

什么情况下会触发重排?

  1. 可见 DOM 元素的增删
  2. 元素素位置、尺寸变化(宽度、高度、边距、填充、边框等)
  3. 元素内容变化(文本变化,图片变化)
  4. 浏览器可视窗口变化
  5. 计算某些布局信息(如offsetTop、getComputedStyle等方法)

什么情况下会触发重绘? 修改了 DOM 元素的外观属性,比如颜色,透明度,阴影,边框样式

重排重绘会导致什么问题?

  1. 消耗资源,造成卡顿
  2. 影响页面交互的流畅度,如果JavaScript执行、重排、重绘的时间总和超过16.67毫秒(60fps 屏幕),就会导致帧率下降,动画和滚动等交互效果会变得不流畅。

有哪些手段可以避免重排重绘?(最佳实践)

  1. 尽量避免在重排重绘后,立即读取一些布局属性,此时会打断浏览器本身的批量处理优化,强制同步布局,立即进行重排,造成强制同步布局
  2. 在修改 DOM 时,进行批量的写入和读取(比如先通过虚拟 DOM 做对比,计算出真实 DOM 需要更新的最小集合,再执行真实的 DOM 操作
  3. 在写入样式时,一次性完整写入,且做到读写分离
  4. 避免对样式的频繁操作
  5. 利用特殊的样式属性,比如 transform,opacity,使用合成层更新,开启 GPU 加速。使用 will-change 属性(仅针对复杂动画),提示浏览器将要发生变化。
  6. 使用变量对布局信息进行缓存,避免频繁读取导致的重排
  7. 使动画元素脱离普通文档流(position:fixed,absolute),避免影响其他元素的布局
  8. 避免 table 布局,只要有一个单元格改动,就会造成整个表格重排
  9. 对于复杂操作,可先将元素display设为none,操作完成后再显示,这样只在隐藏和显示时触发两次重排