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
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.
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 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.
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.
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
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) or
visibility: 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
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
cssTextproperty 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:
- use a
documentFragmentto hold temp changes,
- 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
- use a
- In general, think about the render tree and how much of it will need revalidation after your change. For example using absolute positioning
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