浏览器的重绘和回流导致的性能问题

147 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

重绘(Repaint)和回流(Reflow)

重绘和回流是渲染步骤中的一小节,但是这两个步骤对于性能影响很大。

  • 重绘是当节点需要更改外观而不会影响布局的,比如改变 color就叫称为重绘。
  • 回流是布局或者几何属性需要改变就称为回流。
  • 回流必定会发生重绘,重绘不一定会引发回流。
  • 回流所需的成本比重绘高的多,改变深层次的节点很可能导致父节点的一系列回流。

所以以下几个动作可能会导致性能问题:

改变 window 大小改变字体添加或删除样式文字改变定位或者浮动盒模型很多人不知道的是,重绘和回流其实和 Event loop 有关。

当 Event loop 执行完 Microtasks 后,会判断 document 是否需要更新。因为浏览器是 60Hz 的刷新率,每 16ms 才会更新一次。然后判断是否有 resize或者 scroll,有的话会去触发事件,所以 resize和 scroll事件也是至少 16ms 才会触发一次,并且自带节流功能。判断是否触发了 media query更新动画并且发送事件判断是否有全屏操作事件执行 requestAnimationFrame回调执行 IntersectionObserver回调,该方法用于判断元素是否可见,可以用于懒加载上,但是兼容性不好更新界面以上就是一帧中可能会做的事情。如果在一帧中有空闲时间,就会去执行 requestIdleCallback回调。

减少重绘和回流

使用 translate 替代 top

<div class="test">
</div>
<style> 
.testposition: absolute; 
    top: 10pxwidth: 100pxheight: 100pxbackground: red; 
}
</style>
<script> 
setTimeout(() =>// 引起回流 
    document.querySelector('.test').style.top = '100px' 
}, 1000)
</script>

使用 visibility替换 display: none

因为前者只会引起重绘,后者会引发回流(改变了布局)

不要使用 table 布局

可能很小的一个小改动会造成整个 table 的重新布局动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用 requestAnimationFrameCSS 选择符从右往左匹配查找,避免 DOM 深度过深将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于 video标签,浏览器会自动将该节点变为图层。