Improve Performance and Reduce Reflow Repaint

Improve Performance and Reduce Reflow Repaint

Recently I came to know about Reflow and Repaint, how they affect web performance, so I writing this post to give insights about Reflow, Repaints, and how all of this affects our performance and reopen our series about minimizing code.

Critical rendering path

The Critical Rendering Path is the sequence of steps the browser goes through to convert the HTML, CSS, and JavaScript into pixels on the screen. Optimizing the critical render path improves render performance. The critical rendering path includes the Document Object Model (DOM), CSS Object Model (CSSOM), render tree, and layout.

The document object model is created as the HTML is parsed. The HTML may request JavaScript, which may, in turn, alter the DOM. The HTML includes or makes requests for styles, which in turn builds the CSS object model. The browser engine combines the two to create the Render Tree. Layout determines the size and location of everything on the page. Once the layout is determined, pixels are painted on the screen.

Optimizing the critical rendering path improves the time to first render. Understanding and optimizing the critical rendering path is important to ensure reflows and repaints can happen at 60 frames per second, to ensure performant user interactions and avoid jank.

CRP

Document Object Model (DOM)

DOM is incremental. the HTML response tun into tokens which turn into nodes which turn into DOM tree, single DOM starts tag token and end tag token. DOM is connected based on hierarchy. If another set of start tags and end tag tokens come between a set of start tags and end tags, you have a node inside a node, which is how we define the hierarchy of the DOM tree.
The greater the number of nodes, the longer the following events in the critical rendering path will take. Measure! A few extra nodes won’t make a difference, but divitis can lead to jank.

CSS Object Model (CSSOM)

The DOM contains all the content of the page. The CSSOM contains all the styles of the page, information on how to style that DOM. CSSOM is like DOM but it’s different in CSS is
render-blocking, the browser blocks page rendering until it receives and processes all of the CSS. CSS is render-blocking because rules can be overwritten, so the content can’t be rendered until the CSSOM is complete.

Render Tree

render tree captures both content (DOM) and style of the page (CSSOM), combine into a render tree, and to construct the render tree, the browser checks every node, starting from the root of the DOM tree, and determines which CSS rules are attached.
render tree captures visible content and content that is not visible not included in the render tree, not visible content like (meta, script, link) and display: none are omitted from the render tree.

Layout

Once the render tree is built, the layout becomes possible. The layout is dependent on the size of the screen. The layout step determines where and how the elements are positioned on the page, determining the width and height of each element, and where they are in relation to each other.
Layout performance is impacted by the DOM — the greater the number of nodes, the longer layout takes. The layout can become a bottleneck, leading to a jank if required during scrolling or other animations. While a 20ms delay on load or orientation change may be fine, it will lead to a jank on animation or scroll. Any time the render tree is modified, such as by added nodes, altered content, or updated box model styles on a node, layout occurs. to reduce the frequency and duration of layout events, batch updates and avoid animating box model properties.

Paint

finally, paint is the last step in CRP is responsible for painting the pixels to the screen. Once the render tree is created and the layout occurs, the pixels can be painted on the screen. Onload, the entire screen is painted. After that, only impacted areas of the screen will be repainted, as browsers are optimized to repaint the minimum area required. Paint time depends on what kind of updates are being applied to the render tree

for this time I hope you understand what is CRP and how it’s working in the next section I will talk about what repaint and reflow, I know that I have not explained what is reflow so

what is Reflow

A reflow computes the layout of the page. A reflow on an element recomputes the dimensions and position of the element, and it also triggers further reflows on that element’s children, ancestors, and elements that appear after it in the DOM. Then it calls a final repaint. Reflowing is very expensive, but unfortunately, it can be triggered easily.

Reflow occurs when you:

  • insert, remove or update an element in the DOM
  • modify content on the page, e.g. the text in an input box
  • move a DOM element
  • animate a DOM element
  • change a CSS style
  • add or remove a stylesheet
  • resize window

Repaint

A repaint occurs when changes are made to an element’s skin that changes visibly but does not affect its layout. examples of this include outline, visibility, background, or color. repaint is expensive because the browser must verify the visibility of all other nodes in the DOM tree.

What triggers a reflow or a repaint

Anything that changes input information used to construct the rendering tree can cause a repaint or a reflow, for example:

  • Adding, removing, updating DOM nodes
  • Hiding a DOM node with display: none (reflow and repaint) orvisibility: hidden (repaint only, because no geometry changes)
  • Moving, animating a DOM node on the page
  • Adding a stylesheet, tweaking style properties

Browsers are smart

Since the reflows and repaints associated with render tree changes are expensive, the browsers aim at reducing the negative effects. One strategy is to simply not do the work. Or not right now, at least. The browser will set up a queue of the changes your scripts require and perform them in batches. This way several changes that each require a reflow will be combined and only one reflow will be computed. Browsers can add to the queued changes and then flush the queue once a certain amount of time passes or a certain number of changes is reached.

But sometimes the script may prevent the browser from optimizing the reflows, and cause it to flush the queue and perform all batched changes. This happens when you request style information, such as

  1. offsetTopoffsetLeftoffsetWidthoffsetHeight
  2. scrollTop/Left/Width/Height
  3. clientTop/Left/Width/Height
  4. getComputedStyle(), or currentStyle in IE

All of these above are essentially requesting style information about a node, and any time you do it, the browser has to give you the most up-to-date value. In order to do so, it needs to apply all scheduled changes, flush the queue, bite the bullet, and do the reflow.
for example, it’s a bad idea to set and get styles in quick succession (in a loop), like:

el.style.left = el.offsetLeft + 10 + "px";

Minimizing repaints and reflows

The strategy to reduce the negative effects of reflows/repaints on the user experience is to simply have fewer reflows and repaints and fewer requests for style information, so the browser can optimize reflows. How to go about that?

  • Don’t change individual styles, one by one. Best for sanity and maintainability is to change the class names not the styles. But that assumes static styles. If the styles are dynamic, edit the cssText property as opposed to touching the element and its style property for every little change.
// bad
var left = 10,
    top = 10;
el.style.left = left + "px";
el.style.top  = top  + "px";
 
// better 
el.className += " theclassname";
 
// or when top and left are calculated dynamically...
 
// better
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
  • Batch DOM changes and perform them “offline”. Offline means not in the live DOM tree. You can:
    • clone the node you’re about to update, work on the copy, then swap the original with the updated clone
    • hide the element with display: none (1 reflow, repaint), add 100 changes, restore the display (another reflow, repaint). This way you trade 2 reflows for potentially a hundred
  • In general, think about the render tree and how much of it will need revalidation after your change. For example using absolute positioning position: absolute;  or  position: fixed; makes that element a child of the body in the render tree, so it won’t affect too many other nodes when you animate it for example. Some of the other nodes may be in the area that needs repainting when you place your element on top of them, but they will not require reflow.
  • Avoid setting multiple inline styles; avoid setting styles individually. These trigger a reflow for each dynamic style change.
  • Use classNames of elements, and do so as low in the DOM tree as possible.  Changing the class attribute lets you apply multiple styles to an element with a single reflow.  But since this reflows all the element’s children, that means you don’t want to change the class on a wrapper div if you’re only targeting its first child.

in the end all of this, I’ve read about in the last period and love to share if you have any options, opinion anythings pls write it in the comments

Resources

https://www.sitepoint.com/10-ways-minimize-reflows-improve-performance/
https://www.udacity.com/course/browser-rendering-optimization–ud860
https://gist.github.com/faressoft/36cdd64faae21ed22948b458e6bf04d5
https://developer.mozilla.org/en-US/docs/Learn/Performance/CSS

https://gist.github.com/paulirish/5d52fb081b3570c81e3a

One thought on “Improve Performance and Reduce Reflow Repaint
  1. Moaaz

    You should’ve included an example of document fragments as it’s a great and simple technique to minimize reflows/repaints.

    Thank you for the great info

    February 26, 2022 Reply
Leave a Reply

Your email address will not be published.