The detailed process of page rendering

Step1

The browser parses the obtained HTML code into a DOM tree. Each tag in the HTML is a node in the DOM tree. The root node is the document object we commonly use. The DOM tree contains all HTML tags, including elements hidden with display: None, elements added dynamically with JS, etc.

Step2

The browser parses all styles (user-defined CSS and user agents) into a style structure (CSSOM tree). In the process of parsing, it removes styles that the browser does not recognize, such as IE removing styles that begin with -moz and FF removing styles that begin with _.

Step3

DOM tree and style structure (CSSOM tree) are combined to construct the Render tree. Render Tree is similar to DOM Tree, but very different. Render Tree recognizes styles, each NODE in the Render Tree has its own style, and the Render Tree does not contain hidden nodes (such as the display: None NODE, and the head NODE), because these nodes are not used for rendering. And it won’t affect rendering, so it won’t be included in the Render Tree. Note that hidden elements will still be included in the Render tree because visibility: Hidden will affect the layout and occupy the space. According to CSS2 standards, each node in the Render Tree is called a Box (Box Dimensions), understanding the page element as a Box with padding, margins, borders, and positions.

Step4

Once the Render Tree is built, the browser can render the page according to the Render Tree.

Reflux and redraw

backflow

Reflow refers to when part (or all) of the Render tree needs to be rebuilt due to changes in element size, layout, hiding, etc. The render tree needs to be recalculated. That is, backflow is when a DOM change affects the element’s geometry (width and height), the browser recalculates the element’s geometry, invalidates the affected part of the rendering tree, and the browser validates the visibility attribute of all other nodes in the DOM tree. Therefore, backflow is inefficient. Each page needs to be refluxed at least once, the first time the page loads. During backflow, the browser invalidates the affected part of the render tree and reconstructs that part of the render tree. When backflow is complete, the browser redraws the affected part to the screen, a process called redraw.

Backflow generation

Backflow occurs when the page layout and geometry properties change. Browser backflow occurs when the structure of the DOM tree changes, such as the addition or removal of nodes, movement, and so on. The browser engine layout process, similar to the tree traversal, is a top to bottom, left to right process. In this process, the current element does not affect previous elements that have already been traversed. So, if you insert an element before the body, the entire document will be rerendered, while inserting an element after it will not affect the previous element. Element size changes (margin, padding, border, width, and height) : When the geometry of a DOM element changes, the relevant nodes in the render tree become invalidated, and the browser reconstructs the invalidated nodes in the render tree based on the changes in the DOM element. Get some properties: When you get some properties, the browser will also trigger a rearrangement to get the correct value. These attributes include: OffsetTop, offsetLeft, OffsetWidth, offsetHeight, scrollTop, scrollLeft, scrollWidth, scrollHeight, clientTop, clientLeft, clientWidth, clientHeight, get ComputedStyle() (currentStyle in IE). Therefore, these values should be cached when used multiple times. Content changes, such as text changes or image size changes caused by the width and height of the calculated value; Page render initialization; The browser window size changes, such as when the resize event occurs.

redraw

Redraw refers to when the attributes of some elements in the Render Tree need to be updated, and these attributes only affect the appearance and style of elements, but do not affect the layout, such as background-color, visibility, outline, etc. Redrawing does not result in rearrangement and does not necessarily accompany reflux.

The relationship between the two

Backflow will certainly cause redrawing, and redrawing will not necessarily cause backflow.

If the frequency of backflow is high, the CPU usage increases significantly. The rearrangement of one element often leads to a series of reactions, even triggering a rearrangement and redrawing of the entire document, which can be costly in performance.

Methods to reduce backflow and redraw

Reducing backflow and redrawing is simply a matter of reducing render Tree operations (incorporating multiple DOM and style changes) and reducing requests for some style information to take advantage of the browser’s optimization strategy. Here’s the solution.

  • Try not to use inline style attribute, operation element style with the way of adding and removing class, implement merge multiple change style attribute operation:
  • When animating an element, you can set the location of the element to absolute or fixed (the animation element is removed from the document flow). This will not affect other elements and reduce the size of the Render Tree that flows back.
  • Cache variables when you need to frequently retrieve property values that cause browser rearrangements.
  • Change the class at the very end of the DOM tree whenever possible.
  • Avoid setting multiple inline styles.
  • The animation effect is applied to elements whose position attribute is absolute or fixed.
  • Sacrifice smoothness for speed.
  • Table layout is not required.
  • Avoid using CSS JavaScript expressions.
  • Avoid changing styles item by item. It is best to change the style property once, or define the style list as class and change the class property once.
  • Avoid looping the DOM. Create a documentFragment or div, apply all DOM operations to it, and finally add it to window.document.
  • You can operate on a display: None element to finally display it. Because DOM operations on display: None do not cause backflow and redraw.
  • Avoid looping through properties such as offsetLeft and save them before looping.