浏览器重绘与回流

Posted WindrunnerMax

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器重绘与回流相关的知识,希望对你有一定的参考价值。

重绘与回流

重绘与回流是浏览器渲染的时候进行的操作,当页面内容发生改变的时候,就会触发重绘或者回流

重绘

当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如​​background-color​​​,则就叫称为重绘​​Repaint​​,重绘不一定触发回流。

回流

当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建,这就称为回流​​Reflow​​​,有些地方也称为重排,可理解为重新布局。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建渲染树,回流一定触发重绘。
​​​Reflow​​​的成本比​​Repaint​​​的成本高得多的多。​​DOM Tree​​​里的每个结点都会有​​reflow​​​方法,一个结点的​​reflow​​​很有可能导致子结点,甚至父点以及同级结点的reflow。在一些高性能的电脑上也许还没什么,但是如果​​reflow​​发生在手机上,那么这个过程就会卡顿与耗电。

触发

  • 当修改CSS样式的时候
  • 当修改网页的默认字体时
  • 当增加、删除、修改​​DOM​​结点时
  • 当​​Resize​​窗口的时候,或是滚动的时候
  • 当移动​​DOM​​的位置,或是做个动画的时候

优化

浏览器的优化

浏览器本身携带一些优化方式,浏览器会把回流和重绘的操作积攒一批,当操作达到一定数量或者到达时间阈值,然后做一次​​reflow​​​,称为异步​​reflow​​​或增量异步​​reflow​​​。但是有些情况浏览器是不会这么做的,例如​​resize​​​窗口,改变了页面默认的字体等等。对于这些操作,浏览器会马上进行​​reflow​​。

最小化操作

由于重绘和回流可能代价比较昂贵,因此最好就是可以减少它的发生次数,为了减少发生次数,我们可以合并多次对​​DOM​​​和样式的修改,然后一次处理掉,或者将样式事先设计好,动态去改变​​class​​。

离线修改DOM

使用​​documentFragment​​​对象在内存里操作​​DOM​​​,在内存中的​​DOM​​​修改就是让元素脱离文档流,当然是不会触发重绘的,将对​​DOM​​的所有修改批量完成,想怎么改就怎么改,然后将节点再放入文档流中,只触发一次回流。

绝对定位

对于复杂动画效果,由于会经常的非常频繁的引起回流重绘,可以使用绝对定位,让它脱离文档流,否则会引起父元素以及后续元素频繁的回流。

避免多层内联样式

通过​​style​​​属性动态设置样式是在操作一个很小的​​DOM​​​片段,容易导致多次回流。避免设置多级内联样式,样式应该合并在一个外部类,这样当该元素的​​class​​​属性可被操控时仅会产生一个​​reflow​​。

末端改动

尽可能在​​DOM​​​树的最末端或者是层级较低的节点改变​​class​​,回流可以自上而下,或自下而上的回流的信息传递给周围的节点。回流是不可避免的,但可以减少其影响。末端节点或者低层级节点的修改可以限制回流的范围,使其影响尽可能少的节点,当然其也有可能引发大面积回流。

平滑度换取速度

​Opera​​​还建议我们牺牲平滑度换取速度,其意思是指若可能想每次​​1​​​像素移动一个动画,但是如果此动画及随后的回流使用了​​100%​​​的​​CPU​​​,动画就会看上去是跳动的,因为浏览器正在与更新回流做斗争。动画元素每次移动​​3​​​像素可能在非常快的机器上看起来平滑度低了,但它不会导致​​CPU​​在较慢的机器和移动设备中抖动。

避免TABLE布局

在布局完全建立之前,​​table​​​经常需要多个关口,因为​​table​​​是个很罕见的可以影响在它们之前已经进入的​​DOM​​​元素的显示的元素。想象一下,因为表格最后一个单元格的内容过宽而导致纵列大小完全改变,这就是为什么所有的浏览器都逐步地不支持​​table​​​表格的渲染。然而有另外一个原因为什么表格布局是很糟糕的主意,即使一些小的变化将导致表格​​table​​中的所有其他节点回流。

CSS3硬件加速

​CSS3​​​硬件加速也就是​​GPU​​​加速,可以​​transform​​​、​​opacity​​​、​​filters​​​这些动画不会引起回流重绘,但是对于动画的其它属性,比如​​background-color​​​这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。但是也会有一些问题,如果为太多元素使用​​css3​​​硬件加速,会导致内存占用较大,会有性能问题。在​​GPU​​​渲染字体会导致抗锯齿无效。这是因为​​GPU​​​和​​CPU​​的算法不同。因此如果不在动画结束的时候关闭硬件加速,会产生字体模糊。

调试

在很多浏览器的开发者工具中提供了渲染操作的性能分析,以谷歌浏览器为例,其​​performance​​​就可以查看各构建过程的性能消耗,在​​Rendering​​​中可以使用​​Paint flashing​​​高亮重绘区域、​​Layout Shift Regions​​​高亮页面进行交互的布局变化、​​FPS meter​​​显示​​FPS​​帧率等操作来进行性能分析测试

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://www.zhangxinxu.com/wordpress/2010/01/%E5%9B%9E%E6%B5%81%E4%B8%8E%E9%87%8D%E7%BB%98%EF%BC%9Acss%E6%80%A7%E8%83%BD%E8%AE%A9javascript%E5%8F%98%E6%85%A2%EF%BC%9F/

以上是关于浏览器重绘与回流的主要内容,如果未能解决你的问题,请参考以下文章

页面的重绘与回流及优化

性能优化: 避免重绘与回流的实现方式

浏览器的重绘与重排

js中的重绘与重排的区别

Web前端性能优化-重绘与回流

浏览器的重绘与重排