This is the 24th day of my participation in the August Text Challenge.More challenges in August

Related articles:

  • 1. Understand CSS thoroughly
  • 2. Understand CSS thoroughly
  • 1. Understand CSS thoroughly
  • 1. Understand CSS thoroughly
  • 1. Understand CSS thoroughly

Do you understand redraw and reflux?

What is it

In HTML, each element can be interpreted as a box, which involves backflow and redraw during browser parsing:

  • Backflow: The layout engine calculates the size and position of each box on the page based on various styles
  • Redraw: After calculating the location, size, and other attributes of the box model, the browser draws it according to the characteristics of each box

The specific browser resolution rendering mechanism is as follows:

  • Parse HTML, generate DOM tree, parse CSS, generate CSSOM tree
  • Combine DOM Tree and CSSOM Tree to generate Render Tree
  • Layout (backflow) : According to the generated rendering tree, backflow (Layout), get the geometry information of nodes (position, size)
  • Painting (repainting) : Get absolute pixels of nodes based on the rendered tree and geometry information from backflow
  • Display: Send the pixel to the GPU and Display it on the page

Backflow is inevitably triggered during the initial rendering phase of the page, which can be interpreted as a page starting with blank elements and then changing the layout by adding new elements

When we make changes to the DOM that result in a change in the DOM’s geometry (such as changing the element’s width, height, or hiding elements), the browser recalculates the element’s geometry and then draws the calculated results

When our changes to the DOM result in a style change (color or background-color) without affecting its geometry, the browser does not need to recalculate the element’s geometry and simply draw the element in a new style, which only triggers a redraw

Two, how to trigger

To reduce the number of backflow and redraw, first understand how backflow and redraw are triggered

What can trigger backflow?

Backflow is mainly used to calculate the location and geometry information of nodes. When the page layout and geometry information change, backflow is required, as shown in the following example:

  • Add or remove visible DOM elements
  • The position of the element changes
  • The size of the element changes (including margins, inner borders, border size, height, width, etc.)
  • Content changes, such as text changes or an image being replaced by another image of a different size
  • At the beginning of the rendering of the page (which you can’t avoid)
  • Browser window size changes (because backflow calculates element position and size based on viewport size)

There are also operations that are easily overlooked: getting the values of specific attributes

OffsetTop, offsetLeft, OffsetWidth, offsetHeight, scrollTop, scrollLeft, scrollWidth, scrollHeight, clientTop, clientLeft, clientWidth, clientHeight

One common feature of these attributes is that they need to be calculated in real time. So the browser also backflows to get those values

This includes the getComputedStyle method, which works the same way

What would trigger a redraw?

Triggering backflow must trigger redraw

A page can be thought of as a blackboard with a small drawn flower on it. Now we want to move this one from the left to the right, so we need to make sure that the right is exactly where we want it to be, shape it (reflux), and then paint it in its original color (redraw)

In addition, there are several other causes of redraw behavior:

  • Color modification
  • Text direction modification
  • Shadow modification

Browser optimization mechanism

Because each reordering causes additional computation overhead, most browsers optimize the reordering process by queuing changes and executing them in batches. The browser queues changes until a certain amount of time has passed or a threshold has been reached

The operations that force a queue refresh when you get the layout information, including the offsetTop methods, return the latest data

So the browser has to clear the queue, triggering a backflow redraw to return the correct value

Third, how to optimize

We learned how to trigger backflow and redraw scenarios, and here are some lessons to avoid backflow:

  • If you want to style an element, change the element’sclassClass name (at the innermost level of the DOM tree if possible)
  • Avoid setting multiple inline styles
  • Apply the element to the animation, usingpositionProperties of thefixedValue orabsoluteValue (as mentioned in the previous example)
  • Avoid the use oftableThe layout,tableChanges in the size and content of each element in thetableRecalculation of
  • For complex animations, set them upposition: fixed/absoluteKeep elements out of the document flow as much as possible to minimize impact on other elements
  • Using CSS3 hardware acceleration, you can maketransform,opacity,filtersThese animations do not cause backflow redraw
  • Avoid using CSSJavaScriptexpression

When inserting multiple nodes dynamically using JavaScript, you can use the DocumentFragment. Create after insert. You can avoid multiple rendering performance

But there are times when we can’t avoid reflow or redraw, and we can use them better

For example, if we change the layout of an element several times, we might do something like this

const el = document.getElementById('el')
for(let i=0; i<10; i++) { el.style.top = el.offsetTop +10 + "px";
    el.style.left = el.offsetLeft + 10 + "px";
}
Copy the code

Each loop needs to fetch offsets multiple times. Worse, you can cache them as variables and submit them to the browser for recalculation

// Cache offsetLeft and offsetTop
const el = document.getElementById('el')
let offLeft = el.offsetLeft, offTop = el.offsetTop

// Perform calculations at the JS level
for(let i=0; i<10; i++) { offLeft +=10
  offTop  += 10
}

// Apply the calculation results to the DOM once
el.style.left = offLeft + "px"
el.style.top = offTop  + "px"
Copy the code

We can also avoid changing styles and use class names to merge styles

const container = document.getElementById('container')
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'
Copy the code

Use class names to merge styles

<style>
    .basic_style {
        width: 100px;
        height: 200px;
        border: 10px solid red;
        color: red;
    }
</style>
<script>
    const container = document.getElementById('container')
    container.classList.add('basic_style')
</script>
Copy the code

The former triggers a render tree change each time it operates separately (new browsers don’t),

Trigger a render tree change, resulting in a backflow and redraw process

After the merge, we are issuing all the changes at once

We can also remove the element from the page by setting the display: None attribute, and then do subsequent operations that do not trigger backflow and redraw, a process called offline operations

const container = document.getElementById('container')
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'
Copy the code

After offline operation

let container = document.getElementById('container')
container.style.display = 'none'
container.style.width = '100px'
container.style.height = '200px'
container.style.border = '10px solid red'
container.style.color = 'red'
/ /... (Omits many similar subsequent operations)
container.style.display = 'block'
Copy the code