Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most efficient way to modify DOM elements and limit reflow?

When working with a very dynamic UI (think Single Page App) with potentially large JS libraries, view templates, validation, ajax, animations, etc... what are some strategies that will help minimize or reduce the time the browser spends on reflow?

For example, we know there are many ways to accomplish a DIV size change but are there techniques that should be avoided (from a reflow standpoint) and how do the results differ between browsers?

Here is a concrete example:

Given a simple example of 3 different ways to control the size of a DIV when the window is resized, which of these should be used to minimize reflows?

http://jsfiddle.net/xDaevax/v7ex7m6v/

//Method 1: Pure Javascript
function resize(width, height) {
    var target = document.getElementById("method1");
    target.setAttribute("style","width:" + width + "px");
    target.setAttribute("style", "height:" + height + "px");
    console.log("here");
} // end function
window.onresize = function() {
    var height = (window.innerHeight / 4);
    var width = (window.innerWidth / 4);
    console.log(height);
    resize(height, width);
}
//Method #3 Jquery animate
$(function() {
    $(window).on("resize", function(e, data) {
        $("#method3").animate({height: window.innerHeight / 4, width: window.innerWidth / 4}, 600)
    });
});
like image 234
xDaevax Avatar asked Sep 26 '14 15:09

xDaevax


1 Answers

It's best to try and avoid changing DOM elements whenever possible. At times you can prevent reflow at all by sticking to CSS properties or, if required, using CSS' transforms so that the element itself is not affected at all but, instead the visual state is just changed. Paul Lewis and Paul Irish go into detail about why this is the case in this article.

This approach will not work in all cases because sometimes it's required to change the actual DOM element, but for many animations and such, transforms brings the best performance.


If your operations do require reflow, you can minimize the effect it has by:

  • Keeping the DOM depth small
  • Keeping your CSS selector simple (and saving complicated ones to a variable in JavaScript)
  • Avoiding inline styles
  • Avoiding tables for layout
  • Avoiding JavaScript whenever possible

Nicole Sullivan posted a pretty good article on the subject that goes into more details of browser reflows and repaints.

If you're actually changing the DOM, not DOM properties, it's best to do it in larger chunks rather than smaller ones like this Stack Overflow post suggests.


In the example you provided, the second method is the best because it is using CSS properties without needing JavaScript. Browsers are pretty good at rendering elements who's dimensions and position is determined solely by CSS. However, it's not always possible to get the element where we need to be with pure CSS.

The worst method is by far the third because jQuery's animate is terribly slow to start out with, but making it fire on resize makes the animates stack on top of each other so it lags wayyy behind if you resize it much at all. You can prevent this by either setting a timeout with a boolean to check whether it's been fired already or, more preferably, don't use jQuery's animate to do this at all but instead use jQuery's .css() since the resize function fires so often that it will look animated anyway.

like image 142
Zach Saucier Avatar answered Sep 22 '22 14:09

Zach Saucier