Article from Google - Understanding the Impact of DOM Reflow on Javascript Performance

Is there evidence to support the claim that following the advice provided here (as shown below) on removing DOM elements before altering them and then re-inserting them actually results in faster performance?

I'm looking for concrete figures to back up this assertion. While it's great that research has been conducted on this topic, I believe the article lacks specifics on how the 'problem' is defined and how the proposed solution improves speed (as indicated by the article title Speeding up JavaScript).

The article describes a pattern called Out-of-the-flow DOM Manipulation which involves creating multiple elements outside of the DOM using a DocumentFragment before inserting them into the DOM to trigger a single reflow.

The problem

Consider a function that updates the className attribute for all anchors within an element. The conventional approach would involve iterating through each anchor and updating their attributes individually, resulting in a reflow for each anchor.

function updateAllAnchors(element, anchorClass) {
  var anchors = element.getElementsByTagName('a');
  for (var i = 0, length = anchors.length; i < length; i ++) {
    anchors[i].className = anchorClass;
  }
}

The solution

To address this issue, the article suggests temporarily removing the element from the DOM, updating all anchors, and then reinserting the element back to its original position. A reusable function named removeToInsertLater is provided to facilitate this process.

/**
 * Remove an element and provide a function that inserts it into its original position
 * @param element {Element} The element to be temporarily removed
 * @return {Function} A function that inserts the element into its original position
 **/
function removeToInsertLater(element) {
  var parentNode = element.parentNode;
  var nextSibling = element.nextSibling;
  parentNode.removeChild(element);
  return function() {
    if (nextSibling) {
      parentNode.insertBefore(element, nextSibling);
    } else {
      parentNode.appendChild(element);
    }
  };
}

By utilizing this function, we can efficiently update anchors within an out-of-the-flow element, minimizing reflows during the removal and insertion stages.

function updateAllAnchors(element, anchorClass) {
  var insertFunction = removeToInsertLater(element);
  var anchors = element.getElementsByTagName('a');
  for (var i = 0, length = anchors.length; i < length; i ++) {
    anchors[i].className = anchorClass;
  }
  insertFunction();
}

Answer №1

Obtaining accurate data for this issue through JavaScript profiling can be challenging, as the focus is primarily on minimizing repaints and reflows which may not be easily detectable in most profiling tools. One helpful tool you can utilize is the Firebug paint events extension, which visually illustrates the number of repaints you are able to prevent.

Answer №2

After adding links to a page and testing a method mentioned in an article, I compared it to manually setting the class name of elements on the same page. This was tested in Firefox 3, IE 8, and Chrome 3.

I created classes for the links with different colors and font sizes. Since the link text varied in size based on the class, it became evident that the page had to be reflowed.

Removing and adding elements is slightly slower for a reasonable number of links (up to a few thousand).

Surprisingly, for an extremely large number of links (10,000), removing and adding elements is slightly faster.

However, this difference is minimal. It requires several thousand links to even notice any change, and at 10,000 links, there is only about a 20% variance.

In conclusion, don't expect a significant transformation from this method. If you are facing performance issues, other methods may yield better results. For instance, changing the class name of the parent element instead of individual child elements and letting CSS handle the rest could be approximately ten times faster based on previous tests I have conducted.

Answer №3

Incorporating documentFragments to initialize elements instead of the dom is akin to streamlining the process for faster performance. Document fragments are more efficient because they involve less structure and rendering compared to traditional methods.

John Resig's insights on the advantages of using document fragments for performance optimization, as seen in jquery:

http://ejohn.org/blog/dom-documentfragments/

Answer №4

In simple terms, any modifications made to the Document Object Model (DOM) of a webpage will trigger events in Javascript, evaluations in CSS, and have a ripple effect on other parts of the DOM. On the other hand, isolated nodes not connected to the main structure do not have these complexities, making manipulations much more efficient.

To put it another way: Imagine you are an animator working on a movie like Toy Story 4. Would you make changes to the fabric physics of a scene by constantly rendering full-detail images to check each adjustment, or would you simplify the visuals while focusing on perfecting those details?

Answer №5

It's difficult to determine exactly when a reflow has completed, so the best way is to visually inspect the page.

The time it takes to calculate changes remains consistent whether elements are added or altered all at once or one by one. The script doesn't pause between elements, allowing the browser to catch up as needed.

Sometimes immediate visibility of an element is preferred, even if it means waiting longer for the entire content to load. Other times, it may be better to wait slightly longer and display everything simultaneously when complete.

If unsure about which approach is more effective, consulting with a designer to review both single-item and bulk update versions is recommended - but avoid conflicting advice from multiple designers!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The redirection of the URL after form submission is not functioning correctly

I'm attempting to develop a pair of dropdown lists in Elementor where the second dropdown's options depend on what is selected in the first, and the second contains URLs linked to a GO button that redirects to the chosen URL. However, I've f ...

Utilizing Ajax and jQuery to verify the initial password input in real-time as the user types

My goal is to create a Change Password page where users can enter their original password and have it instantly checked for correctness without the need for page refresh. I want to display a checkbox image next to the text box when the password is correct. ...

Is there a way to make a text area move along with the mouse cursor?

I have been working on my first website and everything is running smoothly so far. However, I have a new idea that I am struggling to implement. Some of the pages on my site feature a video player with buttons to select different videos. When a viewer hove ...

Deliver static assets integrated within Express using HTML template

I have a directory of text files that I'm currently serving through Express using express.static. Here's the code snippet: const express = require('express') const app = express() const port = 3000 var serveIndex = require('serve- ...

Rails application experiencing difficulties in displaying the Raty JS plugin

Encountering issues with the raty js plugin while working on Rails version 5.0. jquery.raty.self-628421be04f36f7a8fa8b9b884c6d7824d6f8bdeba4f172b131f15aa63f713e8.js?body=1:761 Uncaught ReferenceError: jQuery is not defined at jquery.raty.self-628421be ...

What could be the reason that my function is being executed twice?

I am encountering an issue with a function that is being called within another function. This function is supposed to return values from a json object, and these values change depending on the filters I have configured. However, for some reason both value ...

Storing JavaScript Array for Future Use in a Separate File

Trying to clarify my question: I'm working with two files: number-crunching.js and chart.html. The number-crunching.js file contains a JSON object: var data = [ { "mother": "Ellen", "father": "Bob", "pet": "cat", "age":50, "hairLength":10 ...

The JMeter JSR223 Sampler and WebDriver Sampler do not support the Javascript language

I am currently working on integrating Selenium Webdriver Sampler with JMeter. Although I have been following tutorials, I have encountered an issue where the script language dropdown in the sampler screen does not include an option for JavaScript, prevent ...

Uncovering the key based on the value in MongoDB

I'm currently working with Node.js using the express framework and Mongoose for MongoDB, and I've got a query regarding efficient data retrieval. Imagine having a mongo document structured like this: test : {a:1, b:2, c:2, d:1}; While it' ...

Displaying "Loading..." with jQuery in Bootstrap 4 while utilizing the data-loading-text feature

I am attempting to create a loading effect for a button, similar to the example shown on codepen. My project utilizes bootstrap 4 (beta 2) and Jquery 3.2.1. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> &l ...

Does adding .catch resolve a promise?

Being new to typescript / javascript, I have limited knowledge about promises. My current scenario involves creating three distinct promises within a cloud-function and subsequently returning them using Promise.all([promise1, promise2, promise3]). Each of ...

JQuery failing to trigger AJAX function

I'm struggling with what seems like a simple issue and it's driving me crazy. The problem lies in this straightforward section of the website. I have a .js file that uses ajax to save a post into the database when the submit button is clicked. A ...

Parsing JSON data received through a URL using Ruby

When attempting to send a JSON object from JavaScript to Ruby, I am encountering issues with parsing it in Ruby. Despite trying various methods and conducting extensive research, I have not been able to find a solution. It is important to note that I am r ...

Exploring Angular.js: A Guide to Implementing Dynamic Menus

Currently, I am in the process of transitioning an application from jQuery to Angular, which has proven to be quite challenging for me. I'm seeking assistance with routing and loading controllers for different user types upon login - specifically stud ...

What is the best way to retrieve the values of "qty" and "price" and access them within the item [array] without knowing the IDs?

I am currently working on a shopping cart project, specifically on the "previous orders" page to display order details. My goal is to output this information in an (.ejs) file. The data structure includes nested objects, and within one object, propertie ...

"How can I update a table in Flask using Chart.js and Pandas

I have developed a basic Flask application that includes a bar chart using Chart.js and a data table displayed below it. Check out the setup below: https://i.sstatic.net/QB6jQ.png (Live view: ) The bar chart I created counts the number of items for each ...

Fixing the Material UI upgrade error: "Make sure you have the right loader for this file type."

As a beginner in React, Webpack, Babel, and web development, I have been tasked by my company to upgrade the material-ui version for a dropdown search component. The current version used in the project is "1.0.0-beta.43", and I decided to start by upgradin ...

The React Redux Saga triggers multiple API calls in a loop

I'm encountering an issue while fetching records in redux saga. There seems to be a strange behavior where calling an action in useEffect from the class triggers multiple calls in a loop, leading to endless API requests. Could someone please point ou ...

What is the process for integrating Socket io into an external JavaScript file that is connected to an HTML file?

Currently, I am utilizing node js, socket io, and express to develop a multiplayer web game. To begin, the server initiates and listens on port 2000. Upon visiting localhost:2000, the file lobby.html is transmitted using: //app.js const express = require ...

Tips for ensuring a cloned table header remains fixed when scrolling through a page

Check out my code snippet on Pastebin: http://pastebin.com/pUstKXJz I'm trying to make a sticky header that stays at the top of the page when I scroll past 100 pixels. The current JQuery code I have isn't working properly, so I need help modifyi ...