First talk about two points

Backflow will certainly cause redrawing, redrawing will not necessarily cause backflow;

Backflow costs more than repainting;

backflow

When some or all of the nodes in the Render Tree need to be rebuilt due to changes in the size, layout, hiding, etc., and their exact positions and sizes in the device viewport are calculated, the process of the browser rerendering is called backflow.

Operations that cause backflow:

  • Page rendered for the first time.
  • The browser window size changed. Procedure
  • The size or position of the element changed.
  • Element content changes (the number of words or image size changes).
  • Element font size changes.
  • Add or removevisibletheDOMElements.
  • The activationCSSPseudo-classes (eg::hover).
  • Query some properties or call some methods.

Some common properties and methods that cause backflow.

  • clientWidth,clientHeight,clientTop,clientLeft
  • offsetWidth,offsetHeight,offsetTop,offsetLeft
  • scrollWidth,scrollHeight,scrollTop,scrollLeft
  • scrollIntoView(),scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

redraw

When a change in the style of an element (color, background-color, etc.) in a page does not affect its surrounding or internal layout (size, size, etc.), the browser assigns the new style to the element and redraws it, a process called redraw.

CSS that is easy to redraw

  • color
  • Border style border-style
  • The rounded border – the radius
  • Text decoration text-decoration
  • Shadow box – shadow
  • Outline the outline
  • Background background

Pay attention to

Induction reflow

In some cases, such as modifying the elements of style, the browser will not immediately reflow or repaint once, the browser will maintain a queue, put all cause re-flow and re-paint operation in the queue, if the number of tasks in the queue or interval reaches a certain critical value, the browser will turn to perform, a batch, The queue is emptied so that multiple reflows and redraws become one, also known as asynchronous reflow or incremental asynchronous reflow.

Immediately reflow

In some cases, the queue will be forced to empty, i.e. forced backflow, such as the resize window, changing the default font of the page, etc.

When the following properties or methods are accessed, the browser immediately clears the queue and reflow immediately:

  • clientWidth,clientHeight,clientTop,clientLeft
  • offsetWidth,offsetHeight,offsetTop,offsetLeft
  • scrollWidth,scrollHeight,scrollTop,scrollLeft
  • scrollIntoView(),scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

Css3 does not require backflow and redraw:

  • Transform // Apply 2D or 3D transformations to elements. This property allows you to rotate, scale, move, or tilt elements
  • Opacity // Sets the opacity level of the element
  • Filter // defines elements (usually) visual effects (e.g. Blur and saturation)
  • Will-change // Notify the browser in advance of what we want to animate the element so that the browser can prepare appropriate optimization Settings in advance

Browser drawing DOM

1. Obtain the DOM and divide it into multiple layers; 2. Draw each layer into a separate bitmap; 3.

Typically, the browser will draw the contents of a layer into a bitmap and then upload it to the GPU as a texture. As long as the contents of the layer do not change, there is no need to repaint. The browser will recomposite the contents to form a new frame.

The transform does not redraw because the transform is a composite property. When you animate a composite property, a composite layer is created. This allows animation elements to be rendered in a separate layer. When the content of the element has not changed, there is no need to redraw it. The browser creates the animation frame by recomposing it.

Optimized reflux reduction

There is no change in orientation, only a fading

Try to set the element to visibility because display: None causes backflow and visibility only causes redraw.

Avoid the use oftablelayout

Try not to use a table layout. If there is no fixed width and the width of a table column is determined by the widest column, it is likely that the last row will be wider than the previous column width, causing an overall backflow and causing the table to need multiple computations to determine the attributes of its nodes in the render tree, often taking three times as long as the equivalent element.

For complex animation effects, use absolute positioning to keep them out of the document flow

For complex animation effects, which often cause backflow redrawing, try to set elements to absolute or fixed, so that they are removed from the document stream. When operating on the location attribute of an element, only this element will be backflowed, otherwise it is easy to cause frequent backflows of the parent element and subsequent elements.

Merge style changes

Reduce the amount of backflow. If multiple CSS properties are being manipulated on a node, and each one causes backflow, it is better to rewrite the style property at once, or define the style list as class and change the class property at once (rather than using JS to change each style individually).

Batch operation DOM

Special handling is required to reduce backflow when multiple operations are performed on the DOM. Multiple operations on an element after leaving the standard flow do not trigger backflow. When the operation is complete, the element is put back into the standard stream.

There are three types of operations that deviate from the standard flow:

  1. Hide elements (display: None, only causes two reflow and redraw)
  2. Using document fragments (createDocumentFragment: Create a virtual documentFragment node)
  3. Copy the node

Example: The following multiple operations on the DOM node trigger backflow each time

Var data = [{id: 1, name: "1" goods,}, {id: 2, name: "1" goods,}, {id: 3, name: "1" goods,}, {id: 4, name: "1" goods,}, / / assumptions behind many]; var oUl = document.querySelector("ul"); for(var i=0; i<data.length; i++){ var oLi = document.createElement("li"); oLi.innerText = data[i].name; oUl.appendChild(oLi); }Copy the code

In this way, each operation to add a LI to ul triggers backflow each time.

Method 1: Hide the UL, add a node to the UL, and then display the UL

oUl.style.display = 'none'; for(var i=0; i<data.length; i++){ var oLi = document.createElement("li"); oLi.innerText = data[i].name; oUl.appendChild(oLi); } oUl.style.display = 'block';Copy the code

At this point, backflow is triggered twice when ul is hidden and ul is shown, and no backflow is triggered when each LI is added to ul.

Method 2: Create a document shard, put all li in the document shard first, and then put the document shard in ul

var fragment = document.createDocumentFragment(); for(var i=0; i<data.length; i++){ var oLi = document.createElement("li"); oLi.innerText = data[i].name; fragment.appendChild(oLi); } oUl.appendChild(fragment);Copy the code

DocumentFragment represents a minimal document object that has no parent file. The biggest difference from Document is that DocumentFragment is not part of the real DOM tree, and changes to it do not trigger the DOM tree (re-rendering) or cause performance issues.

The use of the document. CreateDocumentFragment method or constructor to create an empty DocumentFragment.

detailed

Method 3: Make a copy of ul, put all li in the copy, and replace ul with a copy (deep copy) when all li are in the copy.

var newUL = oUl.cloneNode(true); for(var i=0; i<data.length; i++){ var oLi = document.createElement("li"); oLi.innerText = data[i].name; newUL.appendChild(oLi); } oUl.parentElement.replaceChild(newUl, oUl);Copy the code

Pay attention to

CloneNode () stands for shallow copy – the element in the tag, the event is not copied. CloneNode (true) stands for deep copy – copying exactly what’s in the real node

Avoid triggering layouts more than once

Retrieves an element’s scrollTop, scrollLeft, scrollWidth, offsetTop, offsetLeft, offsetWidth, offsetHeight and other attributes. So if you’re going to do it multiple times, you might want to cache it.

Back to the top operation as follows:

goBack.onclick = function(){ setInterval(function(){ var t = document.documentElement.scrollTop || document.body.scrollTop; t += 10; document.documentElement.scrollTop = document.body.scrollTop = t; }}, 20)Copy the code

Every 20 milliseconds, the scrolling distance is reacquired, and each time a backflow is triggered. The code is optimized as follows:

goBack.onclick = function(){ var t = document.documentElement.scrollTop || document.body.scrollTop; setInterval(function(){ t += 10; document.documentElement.scrollTop = document.body.scrollTop = t; }}, 20)Copy the code

Get it only once, increasing the number each time to avoid getting the scrolling distance each time.