Another RayJune

一目了然的 reflow repaint

综合了 google 对于 reflow 的优化实践和 stubbornella.org 上对于 reflow 和 repaint 讲解,力求一目了然的效果。

Concise explanation

repaint

在对某个 DOM 元素做非 layout 修改的时候(如 background-colorvisibility)会导致这个元素的 repaint。

性能代价在于浏览器必须验证 DOM 树上其他节点元素的 visibility

reflow

在对某个 DOM 元素做关于 layout 修改的时候(如 width)会导致:

  • 这个元素需要 reflow
  • 它的子元素需要 reflow
  • 可能它的父元素需要 reflow
  • 可能与它相关的元素需要 reflow
  • 大部分时候会导致,全局 reflow

因此性能消耗很大,有 User blocking 之说,要格外注意这种情况,过多 reflow 很影响用户体验。

优化 reflow 的方法

因为 reflow 对性能的影响更大,又因为 reflow 和 repaint 不可避免,下面有几种尽量减少 reflow 影响的方法:

  1. 减少操作 DOM 时不必要的 DOM 深度(比如操作父节点来控制子节点的表现),从而减小需要 reflow 的 DOM 元素的范围。
  2. 最小化 CSS 规则,去除无用的 CSS 规则
  3. 动画效果最好用 postion: absoluteposition: fixed 来固定,这样可以将大范围的 reflow 变成单一范围的 repaint
  4. 去除无用的 CSS 选择器深度,因为它会消耗较大 CPU 资源去匹配复杂的选择器
  5. 避免大量设置 inline style(如 <p style="font-weight: border">Another RayJune</p>),style 应该都被设置在外部的一个 class 中,用修改 class 的方式修改 style 只产生一次 reflow
  6. 对于动画、VR/AR 等需要高性能支持的功能,如果将它的变化速率的很快,会消耗大量 CPU 资源,这时可以选择慢一些的变化速率,可能会得到同样的效果
  7. 不用 table layout
  8. 避免 CSS 中写 JavaScript(相信已经没有人这么做了)

福利

A website can search which attribute will trigger repaint or reflow
https://csstriggers.com/z-index

Reference

以下为自己看 stubbornella.org 以及 google 关于 repaint、reflow 做的小记。

stubbornella.org 上的经典文章

http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/

What is repaint

A repaint occurs when changes are made to an elements skin that changes visibility, but do not affect its layout. (such as background-color)

Repaint is expensive because the browser must verify the visibility of all other nodes in the DOM tree.

What is reflow

A reflow is even more critical to performance because it involves changes that affect the layout of a portion of the page (or the whole page).

For the purpose of re-rendering part or all of the document.

Reflow of an element causes the subsequent reflow of all child and ancestor elements as well as any elements following it in the DOM.

How to avoid reflows or at least minimize their impact on performance?

Change classes as low in the dom tree as possible

Reflows can be top-down or bottom-up as reflow information is passed to surrounding nodes.

Reflows are unavoidable, but you can reduce their impact.

Change classes as low in the dom tree as possible and thus limit the scope of the reflow to as few nodes as possible.
减少要操作的 DOM 级别,将回流的范围限制在尽可能小的节点区域

For example, you should avoid changing a class on wrapper elements to affect the display of child nodes.

Object oriented css always attempts to attach classes to the object (DOM node or nodes) they affect, but in this case it has the added performance benefit of minimizing the impact of reflows.

Avoid setting multiple inline styles

We all know interacting with the DOM is slow. We try to group changes in an invisible DOM tree fragment and then cause only one reflow when the entire change is applied to the DOM.

Similarly, setting styles via the style attribute cause reflows.

Avoid setting multiple inline styles which would each cause a reflow, the styles should be combined in an external class which would cause only one reflow when the class attribute of the element is manipulated.

Apply animations with position fixed or absolute

Apply animations to elements that are position fixed or absolute.

They don’t affect other elements layout.

So they will only cause a repaint rather than a full reflow. This is much less costly.

Trade smoothness for speed

Opera also advises that we trade smoothness for speed.

What they mean by this is that you may want to move an animation 1 pixel at a time, but if the animation and subsequent reflows use 100% of the CPU the animation will seem jumpy as the browser struggles to update the flow.

Moving the animated element by 3 pixels at a time may seem slightly less smooth on very fast machines, but it won’t cause CPU thrashing on slower machines and mobile devices.

Avoid tables for layout (or set table-layout fixed)

Even minor changes will cause reflows of all other nodes in the table.

Avoid JavaScript expressions in the CSS

The main reason these expressions are so costly is because they are recalculated each time the document, or part of the document, reflows.

As we have seen from all the many things that trigger a reflow, it can occur thousands and thousands of times per second. Beware!

google 关于优化 reflow 的指导

https://developers.google.com/speed/articles/reflow?csw=1

In many cases, they are equivalent to laying out the entire page again.

Because reflow is a user-blocking operation in the browser, it is useful for developers to understand how to improve reflow time and also to understand the effects of various document properties (DOM depth, CSS rule efficiency, different types of style changes) on reflow time.

At Google, we test the speed of our web pages and applications in a variety of ways - and reflow is a key factor we consider when adding features to our UIs. We strive to deliver lively, interactive and delightful user experiences.

guidelines

  • Reduce unnecessary DOM depth. Changes at one level in the DOM tree can cause changes at every level of the tree - all the way up to the root, and all the the way down into the children of the modified node. This leads to more time being spent performing reflow.
  • Minimize CSS rules, and remove unused CSS rules.
  • If you make complex rendering changes such as animations, do so out of the flow. Use position-absolute or position-fixed to accomplish this.
  • Avoid unnecessary complex CSS selectors - descendant selectors in particular - which require more CPU power to do selector matching.

文章标题:一目了然的 reflow repaint

文章作者:RayJune

时间地点:下午 14:26,于又玄图书馆

原始链接:http://rayjune.xyz/2017/12/04/concise-reflow-repaint-introduction/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。