reflow repaint 小心重绘与回流,优化浏览器性能

来源:互联网 发布:无线虚能矩阵 编辑:程序博客网 时间:2024/05/12 18:46

转载自张鑫旭-鑫空间-鑫生活
原文翻译 by 张鑫旭 原文地址 :http://www.zhangxinxu.com/wordpress/?p=600

回流(reflows):

如果渲染树的结点发生了结构性变化,例如宽度、高度或者位置上的变化时,那么会触发Reflow(回流)的逻辑。我们第一次进入一个页面时便会至少触发一次这个逻辑。回流是性能的关键,因为其变化涉及到部分页面(或是整个页面)的布局。一个元素的回流导致了其所有子元素以及DOM中紧随其后的祖先元素的随后的回流。

重绘(repaint)

如果渲染树结点发生了非结构性变化,例如背景色等的变化时,那么会触发Repaint(重绘)的逻辑。

注意:回流必将引起重绘,而重绘不一定会引起回流。 我们需要明白,页面若发生回流则需要付出很高的代价。
display:none 引发 reflow 和 repaint
visibility:hidden 仅仅引发了 repaint

既然它们对性能影响如此可怕,那什么会导致回流呢?

1、添加或者删除可见的DOM元素;

2、元素位置改变;

3、元素尺寸改变——边距、填充、边框、宽度和高度

4、内容改变——比如 input 文本改变或者图片大小改变而引起的计算值宽度和高度改变;

5、页面渲染初始化;

6、浏览器窗口尺寸改变——resize事件发生时;

7、改变字体(Changing the font)

8、增加或者移除样式表(Adding or removing a stylesheet)

9、激活 CSS 伪类,比如 :hover (IE 中为兄弟结点伪类的激活)

10、脚本操作 DOM(A script manipulating the DOM)

11、计算 offsetWidth 和 offsetHeight 属性(Calculating offsetWidth and offsetHeight)
等等….

如何避免回流或将它们对性能的影响降到最低

注意:这里我限定了自己只能讨论CSS对回流的影响,

  • 如果想设定元素的样式,通过改变元素的 class 名 (尽可能在 DOM 树的最末端)
  • 避免设置多项内联样式(Avoid setting multiple inline styles)
  • 应用元素的动画,使用 position 属性的 fixed 值或 absolute 值
  • 权衡平滑和速度(Trade smoothness for speed)
  • 避免使用table布局(Avoid tables for layout)
  • 避免使用CSS的JavaScript表达式 (仅 IE 浏览器)(Avoid JavaScript expressions in the CSS (IE only))

尽可能在DOM树的最末端改变class

回流可以自上而下,或自下而上的回流的信息传递给周围的节点。回流是不可避免的,但可以减少其影响。尽可能在DOM树的里面改变class,可以限制了回流的范围,使其影响尽可能少的节点。例如,你应该避免通过改变对包装元素类去影响子节点的显示。面向对象的CSS始终尝试获得它们影响的类对象(DOM节点或节点),但在这种情况下,它已尽可能的减少了回流的影响,增加性能优势。
避免设置多层内联样式

我们都知道与DOM交互很慢。我们尝试在一种无形的DOM树片段组进行更改,然后整个改变应用到DOM上时仅导致了一个回流。同样,通过style属性设置样式导致回流。避免设置多级内联样式,因为每个都会造成回流,样式应该合并在一个外部类,这样当该元素的class属性可被操控时仅会产生一个reflow。

动画效果应用到position属性为absolute或fixed的元素上

动画效果应用到position属性为absolute或fixed的元素上,它们不影响其他元素的布局,所它他们只会导致重新绘制,而不是一个完整回流。这样消耗会更低。
牺牲平滑度换取速度

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

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

避免使用CSS的JavaScript表达式

这项规则较过时,但确实是个好的主意。主要的原因,这些表现是如此昂贵,是因为他们每次重新计算文档,或部分文档、回流。正如我们从所有的很多事情看到的:引发回流,它可以每秒产生成千上万次。当心!

以下是一些简单的指导方针可以帮助你页面上的回流(reflow)减到最小。

  1. 减少不必要的DOM深度。因为无论你改变DOM节点树上任何一个层级都会影响节点树的每个层级——从根结点一直到修改的子节点。不必要的节点深度将导致执行回流时花费更多的时间。
  2. 精简css,去除没有用处的css
  3. 如果你想让复杂的表现发生改变,例如动画效果,那么请在这个流动线之外实现它。使用position-absolute或position-fixed来实现它。
  4. 避免不必要的复杂的css选择符,尤其是使用子选择器,或消耗更多的CPU去做选择器匹配。