Reflow and Repaint can cause performance problems on the PC side as long as you don’t write code with the mindset of “going crazy”. However, mobile rendering capability is more than a fraction of that on the PC side, and a careless reflow and Repaint can become performance killers on the mobile side. So it’s important to understand Reflow and Repaint as a starting point when considering page performance.

What is the


Reflow, or rearrangement. The term reflow refers to the process by which browsers recalculate the location and geometry of elements in a document for the purpose of rerendering part or all of it.

Simply put, reflow is required when the page layout or geometry changes.

Reflow at least once in a page when the page is first loaded. During reflow, the browser invalidates the affected nodes in the Render Tree and reconstructs the Render Tree. Sometimes, even if only a single element is reflow, It may also require its parent element and any elements that follow it to also produce reflux

Repaint: When elements on a page need to be restyled without affecting the layout, such as background-color.

How to trigger


reflow

You can hear some of this from the definition of reflow, which is triggered when the layout and geometry of an element changes. These are the main attributes:

  • Box model-related attributes: width, height, margin, display, border, etc

  • Position properties and float related properties: top,position,float, etc

  • Changing the internal text structure of a node can also trigger backflow: text-align, overflow, font-size, line-height, vertival-align, etc

In addition to the three categories of attribute changes that trigger reflow, the following conditions also trigger reflow:

  • Resize the window
  • Style sheet changes
  • Element content changes, especially input controls
  • Dom manipulation
  • CSS pseudo-classes are enabled
  • Calculate the offsetWidth, offsetHeight, clientWidth, clientHeight, Width, height, scrollTop, scrollHeight of the element

repaint

Redraw is triggered when elements in a page update style-related properties such as background, color, cursor, visibility, etc

Note: From the rendering process of the page, reflow will definitely cause repaint, and repaint will not necessarily cause reflow

To learn which attribute changes trigger backflow or redraw click here

Smart Browser


Imagine a scenario where we need to constantly change the position or content of a DOM node in a loop

   document.addEventListener('DOMContentLoaded'.function () {
    var date = new Date(a);for (var i = 0; i < 70000; i++) {
        var tmpNode = document.createElement("div");
        tmpNode.innerHTML = "test" + i;
        document.body.appendChild(tmpNode);
    }
    console.log(new Date() - date);
}); 
Copy the code

The time consumed for multiple measurements here is about 500ms (the operating environment is PC and The Small Overlord laptop). This may be a bit of a surprise, but there are 70,000 content changes and 70,00reflow, which takes 500ms (thanks to sluggish DOM manipulation), and reflow is a performance drag.

  • offsetTop/Left/Width/Height
  • scrollTop/Left/Width/Height
  • clientTop/Left/Width/Height
  • getComputedStyle(), or currentStyle in IE

The code is as follows:

        document.addEventListener('DOMContentLoaded'.function () {
            var date = new Date(a);for (var i = 0; i < 70000; i++) {
                var tmpNode = document.createElement("div");
                tmpNode.innerHTML = "test" + i;
                document.body.offsetHeight; // Get the real value of the body
                document.body.appendChild(tmpNode);
            }
            console.log("speed time".new Date() - date);
        });
Copy the code

Most people don’t run this code, but if you do, congratulations on your computer -1s. But without metrics, there is no way to optimize performance.

“If you cannot measure it, you cannot improve it.” -Lord Kelvin

To prevent the browser from feigning death, change the number of loops to 7000 and the result is (multiple times average) :

  • The sample with real values took about 18000ms
  • The sample without real values took about 50ms

These two examples confirm that the browser does have small actions to optimize reflow. Smart programmers do not rely on the optimization strategy of the browser. In daily development, they should carefully write the code inside the for loop body when encountering the for loop.

Reduce reflow and Repaint


How to reduce reflow and repaint? Going back to the definition, reflow occurs when the layout or positioning of the page changes, and there are at least two optimizations that can be derived from the definition

  • Reduce reflow operations
  • Replace the property that triggers backflow

Reduce reflow operations

This is essentially to reduce operations on render Tree. Each node of the render tree is visible and contains the content of the node and the corresponding rule style, which is also the biggest difference between the Render Tree and dom number. The main purpose of reducing the reflow operation is to merge multiple reflows and finally feed back into the Render tree. Such as:

1, change the classname directly

    // It's a bad way to write
    var left = 1;
    var top = 2;
    ele.style.left = left + "px";
    ele.style.top = top + "px";
    // A better way to write it
    ele.className += " className1";
Copy the code

Or modify cssText directly:

ele.style.cssText += "; left: " + left + "px; top: " + top + "px;" ;Copy the code

2. Take frequently reflow elements “offline”

  • Using DocumentFragment for cache operation, causing a backflow and redraw;
  • Using display: None causes only two reflows and redraws;
  • Trigger a backflow and redraw using cloneNode(True or False) and replaceChild techniques;

The Dom defines a document fragment as a “lightweight” document that can contain and control nodes, but does not consume as much resources as a full document. While you can’t add a document fragment directly to a document, you can use it as a “repository” where you can hold nodes that might be added to the document in the future. For example, the original sample with the DocumentFragment could be written like this:

    document.addEventListener('DOMContentLoaded'.function () {
        var date = new Date(),
            fragment = document.createDocumentFragment();
        for (var i = 0; i < 7000; i++) {
            var tmpNode = document.createElement("div");
            tmpNode.innerHTML = "test" + i;
            fragment.appendChild(tmpNode);
        }
        document.body.appendChild(fragment);
        console.log("speed time".new Date() - date);
    });
Copy the code

This process does not affect the Render Tree. After the loop is completed, the “inventory” of this “warehouse” is added to the DOM to reduce reflow. The same is true for cloneNode. The principle of using display: None to reduce the performance overhead of reflow is to invalidate nodes from the Render Tree, and then “live” after multiple nodes have passed that trigger the reflow operation.

3. Reduce the number of accesses to flush cache queue attributes and, if necessary, use the cache

// It's a bad way to write
for(let i = 0; i < 20; i++ ) { 
    el.style.left = el.offsetLeft + 5 + "px"; 
    el.style.top = el.offsetTop + 5 + "px"; 
}
// A better way to write it
var left = el.offsetLeft, 
top = el.offsetTop, 
s = el.style; 
for (let i = 0; i < 20; i++ ) { 
    left += 5;
    top += 5; 
    s.left = left + "px"; 
    s.top = top + "px"; 
}
Copy the code

Replace the properties that trigger reflow and Repaint

We can avoid reflow by replacing some of the properties that trigger backflow. For example, translate instead of top and opacity instead of visibility

Sample code:


      
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #react {
            position: relative;
            top: 0;
            width: 100px;
            height: 100px;
            background-color: red;
        }
    </style>
</head>

<body>
    <div id="react"></div>
    <script type="text/javascript">
        setTimeout((a)= > {
            document.getElementById("react").style.top = "100px"
        }, 2000);
    </script>
</body>
</html>
Copy the code

The code is very simple, there is a red square on the page, after 2 seconds its top value will change to “100px”, in order to facilitate the representation of the alternative attributes to avoid reflow here we use Chrome developer tools, part of the screenshot below

  • Recalculate Style, the browser calculates the changed Style
  • Layout, this process is called reflow reflux process
  • Update Layer Tree: Updates the Layer Tree
  • Paint, the process of drawing layers
  • Composite Layers

80 + Layout(73) + 72 + 20 + 69 = 316us

Replace top with translate:

-       position: relative;
-       top: 0;
+       transform: translateY(0);

-       document.getElementById("react").style.top = "100px"
+       document.getElementById("react").style.transform = "translateY(100px)"
Copy the code

Performace screenshots:

280us
The process of reducing Layout by hundreds of milliseconds or even seconds

Let’s try using opacity instead of visibility again.

-            document.getElementById("react").style.transform = "translateY(100px)"            
+            document.getElementById("react").style.visibility = "hidden"            
Copy the code

Performace screenshots:

183us

+            opacity: 1;

-            document.getElementById("react").style.visibility = "hidden"    
+            document.getElementById("react").style.opacity = "0"
Copy the code

According to the above example, it should be drawn that redrawing after using opacity instead of visibility will disappear to achieve the purpose of improving performance. In this case, let’s look at the Screenshot of Performace:

Click on the

In fact, opacity changes do not change the content of this layer, but only the value of the alpha channel of the current layer, which determines whether the layer is displayed or not. However, the element changing on opacity is not a separate layer, but on the document layer, as shown in the Layers screenshot below:

This means that the browser cannot make the alpha channel of the entire layer go to zero because of any opacity 0 element in the layer, so the Layout and Paint processes are created. The solution is very simple to make this element a separate layer

There are two ways to modify the CSS to create a new layer:

  • Will – change: the transform
  • The transform: translateZ (0)

Here we use the next one

+   transform: translateZ(0);
Copy the code

Performace screenshots:

171us

Since the element I’m changing here is very simple, just a simple div, the optimization benefit of reducing the Paint process is not obvious. If the Paint process is millisecond level, the effect of reducing the Paint process is significant.

As you can see from the above two examples of performance optimization benefits from replacing properties that trigger Reflow and Repaint, this approach works, and there are ways to reduce reflow and Repaint in addition to the first reduction in reflow operations and the second replacement properties

  • Reduce the use of tables

  • Speed selection for animation implementation

  • Create a new layer for the animation

    Table’s own style and some very convenient features will facilitate our development, but table also has some inherent performance defects. If you want to modify any cell in the table, it will lead to the Layout of the whole table. If the table is very large, the consumption of performance will have a rising cost.

Use of layers


In the previous example, we created a new layer that implements opacity instead of visibility to reduce the feasibility of repaint. Is there any other application of this layer? The answer is yes, we can take some frequent redraw backflow of DOM element as a layer, then the redrawing of DOM elements, and the influence of reflux will only in the layer, of course, if you create a new layer for each element that will surely have all outsmarted ourselves, remembers the screenshots of the Performance in the process? Finally, the process of Composite Layers is to combine multiple Layers, and the process of having too many Layers will be time-consuming. In fact, this process itself is also time-consuming. In principle, new Layers will be created when necessary to reduce the influence range of redrawing and backflow. To make use of it requires developers to balance in business scenarios. In Chrome you can create layers like this:

  • 3D or Perspective Transform CSS properties
  • Use the video TAB for accelerated video decoding
  • Canvas with 3D(WebGL) context or accelerated 2D context
  • Hybrid plug-ins such as Flash
  • Animate CSS animations on opacity of its own or use an animated Webkit transform element
  • Elements with accelerated CSS filters (GPU accelerated)
  • The element has a descendant node that contains a composite layer
  • Element has a sibling element with a low Z-index that contains a composite layer
  • will-change: transform;

The general idea is that if we use the frequently redrawn DOM element as a layer, the effects of the redrawn and redrawn DOM element will only be on this layer to improve performance. For example, we open Layers in chrome Developer Tools and open a website

conclusion

To recap, we started by talking about what Reflow and Repaint are and how they are triggered, followed by the strategies browsers use to handle them, and finally, how to avoid the performance overhead of reflow and Repaint. We also added a little bit about the meaning of layers and how to use them easily. There are two points to optimize reflow and Repaint:

  • Avoid using CSS properties that trigger reflow and Repaint
  • Limit reflow and Repaint to a single layer

The resources

https://csstriggers.com

http://blog.csdn.net/luoshengyang/article/details/50661553