JavaScript DocumentFragment

By  on  

One of the lessor known but incredibly useful gems within JavaScript is the DocumentFragment.  DocumentFragments allow developers to place child elements onto an arbitrary node-like parent, allowing for node-like interactions without a true root node.  Doing so allows developers to produce structure without doing so within the visible DOM -- an increase of speed is the true advantage.  Let me show you how DocumentFragments are used!

DocumentFragment Example

Let's start with a UL with which we'll inject LI's to:

<ul id="list"></ul>

DOM injections and modifications are taxing, so the fewer the interactions the better;  that's where the DocumentFragment comes in.  The first step is creating the DocumentFragment:

// Create the fragment
var frag = document.createDocumentFragment();

This DocumentFragment act like a pseudo-DOM node -- think of it as a virtual UL element, in this case.  Now it's time to add elements:

// Create numerous list items, add to fragment
for(var x = 0; x < 10; x++) {
	var li = document.createElement("li");
	li.innerHTML = "List item " + x;
	frag.appendChild(li);
}

Elements can be added to the DocumentFragment just as you could a normal DOM node.  Once the tree of DOM nodes is ready to hit the page, simply place the DocumentFragement into its parent (or other DOM placement functions):

// Mass-add the fragment nodes to the list
listNode.appendChild(frag);

Using DocumentFragments is faster than repeated single DOM node injection and allows developers to perform DOM node operations (like adding events) on new elements instead of mass-injection via innerHTML.  Keep DocumentFragment close by when performing lots of DOM operations -- it could speed up your app considerably!

Recent Features

  • By
    How to Create a Twitter Card

    One of my favorite social APIs was the Open Graph API adopted by Facebook.  Adding just a few META tags to each page allowed links to my article to be styled and presented the way I wanted them to, giving me a bit of control...

  • By
    Vibration API

    Many of the new APIs provided to us by browser vendors are more targeted toward the mobile user than the desktop user.  One of those simple APIs the Vibration API.  The Vibration API allows developers to direct the device, using JavaScript, to vibrate in...

Incredible Demos

  • By
    MooTools, Mario, and Portal

    I'm a big fan of video games. I don't get much time to play them but I'll put down the MacBook Pro long enough to get a few games in. One of my favorites is Portal. For those who don't know, what's...

  • By
    Record Text Selections Using MooTools or jQuery AJAX

    One technique I'm seeing more and more these days (CNNSI.com, for example) is AJAX recording of selected text. It makes sense -- if you detect users selecting the terms over and over again, you can probably assume your visitors are searching that term on Google...

Discussion

  1. But test (http://jsperf.com/out-of-dom-vs-documentfragment/3) do not show “an increase of speed” …

    • Andrew Killen

      that’s only testing one browser type, chrome, plus an arbitrary version of android. not really conclusive. When I tested on my machine it was faster on documentFragment. They are both approaching the same way of working, that is to create all of the HTML and then append it after creation.

      The whole point here is not that you should use docuemntFragment or out of DOM approach, its that you should not append to the DOM on every new element added, as was the habit of earlier of coders.

  2. @sergey: Probably depends on your browser, I got about 5-6 % speed gain with your test. http://imgur.com/SjHWF

  3. David

    I ran that test too, and documentFragment was slower on all my browsers.

    I’m on a Mac… documentFragment was always slower on Firefox 16.0.2 and Safari 6.0.1 (3-4 tests); and mixed results (slower and faster) on Chrome 23.

    David

  4. I’ve created revision 7 to show the improvement of using docfragments. As for differences in creating a temp element using createElement vs createDocumentFragment,

    http://stackoverflow.com/questions/3397161/should-i-use-document-createdocumentfragment-or-document-createelement

    has some explanation.

  5. wouldn’t you want to just concat a string and append that once at the end?

    • Not if you want to add events or work with nodes DOM structure.

  6. fbender

    I “fixed” the jsperf test and had a better performance with Fx 17 Mac, Chrome did not show any significant performance difference between the two options.

    http://jsperf.com/out-of-dom-vs-documentfragment/10

    As long as some browsers profit from documentFragment, everybody should use it (well, at least if you do it correctly).

  7. I updated the speed test http://jsperf.com/out-of-dom-vs-documentfragment/11 by adding test without documentFragment, but still outside of DOM. documentFragment have a limitations and sometimes can not be used.

  8. seelts

    But why do so?
    I can do something like:


    var ul = document.createElement('ul');
    var li;
    for (...) {
    li = document.createElement('li');
    ul.appendChild(li);
    }

    smth.appendChild(ul);

    What is the difference?

    • That’s a good option, but sometimes the “main” element is already in the DOM… like your “ul”.

      So you wouldn’t be appending it into in a “phantom” element, but would be rendering it in the DOM itself. That may be a problem when we are thinking about reflow and thousands of elements.

    • Every time you appended the li to the document will causing that the reflow and repaint,repaints and reflows can be expensive, they can hurt the user experience, and make the UI appear sluggish.But with the DocumentFragments ,you just need once repaint,so…as you know,it’s all about performance

  9. I too use the same method as @seelts, and am wondering the same about performance.

  10. Even I’ve never understood the real benefit of this. Why can’t something as suggested by @seelts be used?

    • I’m not an expert on the subject, but I believe it prevents the browser from doing a full page reflow, you see, every time you add an element to the page using javascript the browser scans the entire DOM for things that have to change due to the new element, with document fragment, you simply reflow the element you’re appending the fragment to

    • Though you’d only notice the performance boost with very heavily populated pages, for example, for a project I need to generate 6k divs for some kind of mapping grid, in a case like this it’s pretty essential to use document fragment

  11. What about event listeners? Can we set event listeners on the dom fragment?

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!