Prevent DOM Reflow
Javascript is a really laid back language. You can write a script a hundred different ways and most browsers don’t care. However, as I found out there are consequences for not diligently writing proper code.
I turned Chris Coyier’s datalist pollyfill into a jQuery plugin. Everything seemed perfect and I was rather self-impressed until I saw this issue. I had never heard of DOM reflow before and I was afraid it might be a difficult fix. But after a few google searches it turned out to be really easy.
What was wrong exactly
var $stuff = $('#stuff');
$.each(('this is an array of things that will get added to $stuff').split(' '), function(i, item) {
$('<li />', {
text: item
}).appendTo($stuff);
});
The problem generally occurs when you modify the DOM tree in a loop. In the code
above you can see that I’m appending 12 <li>
s to my <ol id="stuff">
. This
means that the browser is going to update the layout of the DOM 12 times in a
couple of seconds. That’s a lot.
The Fix
var $stuff = $('#stuff'),
temp_items = document.createDocumentFragment(),
temp_item = null;
$.each(('this is an array of things that will get added to $stuff').split(' '), function(i, item) {
temp_item = $('<li />', {
text: item
})[0];
temp_items.appendChild(temp_item);
});
$stuff.append(temp_items);
The best way to fix the problem is to modify the DOM as few times as possible.
So I used document.createDocumentFragment. Why? Because the document fragment is
not part of the DOM tree. Instead it stays in memory and holds all the items you
append to it. Then when you’re ready, you can append the documentFragment
to
$stuff
.
Take it a step further
Using jQuery.each isn’t as fast as a traditional for loop see my test results.
You can run the same tests in your browser on jsperf. You may find it ironic
that I care because I used .split()
instead of writing an array, but I’m fine
with it for this small example.