Document Fragments and why you should use them
Abdulqudus Abubakre

Abdulqudus Abubakre @ibn_abubakre

About: Front end developer, JavaScript enthusiast, Community Builder

Location:
Abuja, Nigeria
Joined:
Jan 3, 2020

Document Fragments and why you should use them

Publish Date: Apr 10 '20
131 13

A document fragment is a fragment of a Document Object Model (DOM) tree, a chunk of tree that's separated from the rest of the DOM.
Before going further, let's talk about browser reflow and how it affects performance.

According to the google developers, reflow is the name of the web browser process for re-calculating the positions and geometries
of elements in the document, for the purpose of re-rendering part or all of the document.

Browser reflow can be caused by resizing the window,
changing the font, adding or removing a stylesheet, activation of a css psuedo-class, a script manipulating the DOM amongst others.
There are are several events other events that could trigger a browser reflow, but our main focus is the DOM manipulation from the script file.

Let's take for example the following data format gotten from restcountries api and we need to display each country, with its flag;

const countries = [
  {
    name: "Afghanistan",
    population: 27657145,
    flag: "https://restcountries.eu/data/afg.svg",
  },
  {
    name: "Åland Islands",
    population: 28875,
    flag: "https://restcountries.eu/data/ala.svg",
  },
  {
    name: "Albania",
    population: 2886026,
    flag: "https://restcountries.eu/data/alb.svg",
  },
];
Enter fullscreen mode Exit fullscreen mode

A simple approach to this would be:

  • loop over each element in the array
  • create a new element
  • append to an element in the DOM.

Here's how we would go about that in code.

// Select the parent element
const parentElement = document.querySelector('.countries');
// Loop over the array of countries and create each element
countries.forEach(country => {
    // Create a new div element
    const countryCard = document.createElement('div');
    // Create a new image element
    const img = document.createElement('img');
    // Set the src attribute of the image to the flag value from the data
    img.src = country.flag;
    // Attach the image to the div we initially created
    countryCard.appendChild(img);
    // Attach the card to parent element
    parentElement.appendChild(countryCard);
});
Enter fullscreen mode Exit fullscreen mode

Seems pretty simple and straightforward, and there seems to be nothing to worry about....if it's not broken, why fix it right?? 😃😃.

But under the hood, for every time we append the countryCard to the parentElement, we're causing a browser reflow. We might not notice any
glitch or drastic decline in performance in this case and that's because we only have three elements in the array, now imagine we had to the same thing for
all the countries and their individual states...you see where this is going?

Lucky for us, the browser provides a DocumentFragment object for us. As explained earlier, the document fragment is basically an interface
that represents a minimal document object (MDN).

It allows us perform actions we would normally perform on the actual DOM
but without the usual side effects, so we can easily create and append new elements without worrying about the numerous browser reflows that could
occur, and after we're done, we attach the fragment back into the DOM, hence only causing a single browser reflow as opposed to the hundreds or thousands of reflows we could have otherwise caused if we didn't use the fragment.

Now let's repeat the same thing we did above, but this time using the document fragment. The first thing we need to do is create the fragment.
That can be done using the DocumentFragment constructor or the createDocumentFragment method.

let fragment = new DocumentFragment();
// or let fragment = document.createDocumentFragment();
const parentElement = document.querySelector('.countries');
// Loop over the array of countries and create each element
countries.forEach(country => {
    // Create a new div element
    const countryCard = document.createElement('div');
    // Create a new image element
    const img = document.createElement('img');
    // Set the src attribute of the image to the flag value from the data
    img.src = country.flag;
    // Attach the image to the div we initially created
        countryCard.appendChild(img);
    // Append card to fragment element
    fragment.appendChild(countryCard);
});
// After iterating, we then insert fragment contents into the DOM
parentElement.appendChild(fragment);
Enter fullscreen mode Exit fullscreen mode

Something really interesting about the DocumentFragment is that the contents of the fragment are actually moved into the DOM, leaving behind
an empty DocumentFragment.
So you don't really have to worry about memory consumption....pretty awesome right? 😉😉

The document fragment is just one of many ways we could improve browser performance. There are several other techniques we could use to improve
performance of our web application

Comments 13 total

  • Diretnan Domnan
    Diretnan DomnanApr 10, 2020

    Pretty neat writeup. I didn't for once consider optimizing for reflow

  • 〄
    Apr 10, 2020

    This is seriously brilliant. I needed this.

  • raddevus
    raddevusApr 10, 2020

    Thanks for writing this up. It was really great.

    This was such a great article that it inspired me to create a simple example CodePen for it.
    You can check it out at : codepen.io/raddevus/pen/WNQbOpK
    It looks like this:
    Country Flags via CodePen

  • Isaac Hagoel
    Isaac HagoelApr 11, 2020

    Beside the additional div in the Dom tree, what is the different between creating the fragment and creating a div (using createElement) and appending all of the elements to it before finally appending it to the Dom? As long as the parent div is not in the Dom there will be no reflows, right?

    • Abdulqudus Abubakre
      Abdulqudus AbubakreApr 11, 2020

      Well, as you rightly mentioned, there's the fact that you'd be creating an additional element, which might or might not be what you wanted to achieve.
      Also when using fragments, the children are effectively moved into the DOM and leaves behind an empty fragment.
      But then again, they both serve the same purpose, and whatever works for you is fine. Some people would suggest using the createElement cause it's faster, some would say to use the DocumentFragment cause it was built for this

    • Yogesh Datir
      Yogesh DatirApr 18, 2020

      If this has to be done multiple times, it will only create an untidy DOM tree with lots of empty divs. Then this will affect accessing DOM elements. For the same reason react also introduced Fragments.

  • Ankit Tanna
    Ankit TannaApr 11, 2020

    Nice one

  • Iboro
    IboroApr 11, 2020

    Performance is such an important issue so this is just great. I particularly love that the fragment acts as a temporary storage and empties itself automatically after use.

  • Manav Misra
    Manav MisraMay 12, 2020

    🤔 I 🤔 using TEMPLATE 🏷 can alleviate some of this too.

  • sumeet sood
    sumeet soodJun 22, 2023

    We can store the elements in array and after completing loop call append method with array.
    `

    `
    function getListContent() {
    let result = [];

    for(let i=1; i<=3; i++) {``
    let li = document.createElement('li');
    li.append(i);
    result.push(li);
    }

    return result;
    }

    ul.append(...getListContent()); // append + "..." operator = friends!
    ``

Add comment