Learn Steps

Javascript: Understanding Repaint and Reflow of DOM for increasing performance

[sgmb id=3]

 

Hey folks,

I guess you have gone through the previous javascript performance articles on dynamic loading, scope and variables and DOM manipulation.

For this time let us start with understanding what is repaint and reflow. For repaints and reflows we must know about DOM tree and render tree.

DOM tree

It is representation of webpage structure.

Render tree

A representation of how the DOM nodes will be displayed.

The render tree has at least one node for every node of the DOM tree that needs to be displayed (hidden DOM elements don’t have a corresponding node in the render tree).

Once these trees are constructed the browser paints the elements on the page.

Whenever there a change in view in webpage that is css change that effects position, width or anything else, the geometry of elements and all the other elements affected is calculated by the browser. This Process is known as reflow. Note that color changes are not included in geometrical change.

Once the reflow is done the browser paints the affected part on the screen this is known as repaint.

Knowing about these two is very important as more your browser have to calculate the reflows more work it needs to do and hence the performance is decreased dramatically.

When does reflows happens.

  • DOM elements are added or removed. Note that these elements must be visible.
  • Elements change position or change size(because of a change in margin, padding, border thickness, width, height, etc.) or content is changed.
  • Page renders initially and window is resized.

Every time a page geometry is changed the reflow is calculated for all the elements that are affected and then the browser repaints.

In modern browser to increase the performance, these changes are done in batches which reduces the number of reflows  and also the number of repaints.

But with ignorance you will kill the capabilities of these browser to work efficiently.

There are conditions when this capability is overridden and reflow is calculated. When does this happens and when does the render tree changes need to be flushed.

Render tree queue is flushed whenever any of these is calculated.

  • Offsets
  • heights and widths
  • Position.
  • getcomputedStyle()

Why this happens?

It happens because the information that need to be processed from these properties have to be precise and thus all the calculation must be done before that particular stage. This is the reason why everything in the render queue is flushed and reflow is calculated.

From the above discussion you may have inferred that we have to minimize the reflows and repaints thus we must use some techniques to do this. What could be those techniques?

One would be the same what browser does always make changes in render tree in batches. Now you must be wondering how to do that? Look at the codes below.

var element = document.getElementById('div_id');
element.style.borderLeft = '10%';
element.style.borderRight = '15%';

Instead of doing this what we can do is below.

var element = document.getElementById('div_id');
element.style.cssText = 'border-left: 10%; border-right:15%;';

Yes this will process the changes in batch and will save one reflow and one repaint.

You can also make the bulk changes by using the classes in css. Add the properties in class and just add the class at the time or remove the class.

var element = document.getElementById('div_id');
element.className = "border-changed";

//CSS
.border-changed{
  border-left: 10%;
  border-right:15%;
}

So you applied the changes in batches and thus reduced the number of repaints and reflows.

Another solution is to create copy of the node made the changes to the copied elements and then replace th node with the new changes.

var old = document.getElementById('nodename');
var clone = old.cloneNode(true);
appendDataToElement(clone, data);
old.parentNode.replaceChild(clone, old);

What actually we are doing in all these solution is to make the changes go to the DOM is as much larger batch as possible. If thats the case we can also use create fragment and made the changes and append it to the DOM. Yes we can do it like this.

var fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
document.getElementById('nodename').appendChild(fragment);

Conclusion 

From the above discussion we concluded that like touching the DOM, we must also not make it calculate reflow and repaint. This increases the performance and make your web app more responsive. Be mindful of repaints and reflows; batch style changes , manipulate the DOM tree “offline,” and cache and minimize access to layout informations.

Also read about different performance improvement articles here.

https://www.learnsteps.com/javascript-increase-performance-by-handling-dom-with-care/

https://www.learnsteps.com/javascript-increasing-performance-by-handling-scopes-smartly/

https://www.learnsteps.com/javascript-increasing-performance-using-dynamic-loading/

Subscribe for more such articles.