o9ws2g
Last Updated: March 06, 2017
·
24.59K
· thomaslindstr_m
Avatar

Why you should always append DOM elements using DocumentFragments

If you ever find yourself appending a series of elements to the DOM, you should always use a DocumentFragment to do just that.

A DocumentFragment is a minimal document object that has no parent. It is used as a light-weight version of document to store well-formed or potentially non-well-formed fragments of XML.
https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment

Why? Not only is using DocumentFragments to append about 2700 times faster than appending with innerHTML, but it also keeps the recalculation, painting and layout to a minimum.

TL;DR: Use DocumentFragments. http://jsperf.com/document-fragment-vs-innerhtml-vs-looped-appendchild

When normally we would do this to append elements:

var i = 0; while (i < 200) {
    div.innerHTML += '<li>My list item #' + i + '</li>';
i++; }

doing this would be much faster (although not optimal):

var i = 0; while (i < 200) {
    var el = document.createElement('li');
    el.innerText = 'This is my list item number ' + i;
    div.appendChild(el);
i++; }

However, this solution suffers from recalculation of styles, painting and layout - a lot of it - something you should be very wary about when building performant web apps.

Read more about recalculation of styles, painting and layout here: http://stackoverflow.com/questions/11623299/what-does-recalculate-layout-paint-mean-in-chrome-developer-tool-timeline-record

Wouldn't it be great if there was some way to bypass recalculating, painting and layout for every single element we added, and rather have it just happen once? There is!

var el;
var i = 0;
var fragment = document.createDocumentFragment();

while (i < 200) {
    el = document.createElement('li');
    el.innerText = 'This is my list item number ' + i;
    fragment.appendChild(el);
i++; }

div.appendChild(fragment);

Instead of appending the elements directly to the document when they are created, append them to the DocumentFragment instead, and finish by adding that to the DOM.

Now there's only one (big) DOM change happening, and because of that we're also keeping the recalculation, painting and layout to an absolute minimum.

Say Thanks
Respond

7 Responses
Add your response

6681
006d06f5315f5b26c2a455d99a084bb6

Did not know this, will check it out. Thx!

over 1 year ago ·
7068
Kong

great post, its funny how a lot of "developers" do just that they append elements while inside a loop not concerning themselves with repaints or reflows... thanks for posting!

over 1 year ago ·
7070
Avatar

Thanks guys! I think reflows and repaints should be lifted "out of the hood," because right now, even in modern developer tools, it's hard to actually understand what causes them and how to track them down.

over 1 year ago ·
21255
Zp0ano7y normal

Thanks man! It helped me improving my code!

over 1 year ago ·
27787

You may also want to move the 'el' declaration outside the loop and just set it with in the loop. It should also increase performance.

12 months ago ·
27798

According to the following, using the "innerText" property does not seem like a good idea (unless things have changed a lot in the past 3 years):
http://stackoverflow.com/a/19032002/5040168

12 months ago ·
28628

But what if I need to append multiple fragments into multiple divs? I mean not only single one as it was in example div.appendChild(fragment);
but something like:
div0.appendChild(fragment[0]);
div1.appendChild(fragment[1]);
div2.appendChild(fragment[2]);
...

4 months ago ·