DEV Community

Marco
Marco

Posted on • Originally published at blog.disane.dev

Mutation Observer: The invisible force in the background of your website 🕵️

The Mutation Observer is your invisible helper in the background, monitoring DOM changes in real time. Learn how to use it! 🕵️


Imagine you are building a dynamic web application that is constantly changing - be it through user interaction, reloading content or changing UI elements. How do you keep track of all the small and large changes that happen in the DOM? This is exactly where the Mutation Observer comes into play! In this article, I'll show you how to use this powerful API to take your web projects to the next level and how to get it running directly in Stackblitz.

Your personal DOM watchdog 🐕

The Mutation Observer is like an invisible watchdog that watches over the DOM of your website. It notifies you when something changes - without having to constantly ask, as was necessary with older methods. The API is flexible and can be customized to your needs, so you can track exactly the changes that are important to you.

With the Mutation Observer you can:

  • Monitor new elements that are added to the DOM.
  • React to the removal of elements.
  • Track attribute changes in real time.
  • Capture text changes within an element.

The Mutation Observer is particularly useful in single-page applications (SPAs), where the DOM often changes without the page being reloaded.

How the Mutation Observer works 👨‍💻

Let's look directly at a simple example. The code can be copied and pasted into Stackblitz so you can try it out right away:

// Select the target element to observe
const targetNode = document.getElementById('myElement');

// Configuration of the Mutation Observer
const config = {
  attributes: true, // Observes changes to attributes
  childList: true, // Observes addition/removal of child nodes
  subtree: true // Observes changes in the entire subtree of the target element
};

// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
  for(let mutation of mutationsList) {
    if (mutation.type === 'childList') {
      console.log('A child node has been added or removed.');
    } else if (mutation.type === 'attributes') {
      console.log(`The attribute ${mutation.attributeName} was modified.`);
    }
  }
};

// Create an instance of the Mutation Observer and start observing
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);

// Optionally, you can stop observing later
// observer.disconnect();

Enter fullscreen mode Exit fullscreen mode

Examples 🚀

To show you how powerful the mutation observer really is, let's take an interactive example that you can test directly in Stackblitz.

Monitor dynamic content changes

This example shows how you can monitor new elements that are added by user interactions, such as a button click.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mutation Observer example</title>
</head>
<body>
  <div id="content">
    <p>Start observing new content</p>
  </div>
  <button id="addButton">New element</button>

  <script>
    const contentContainer = document.getElementById('content');
    const addButton = document.getElementById('addButton');

    // Configure the Mutation Observer
    const config = { childList: true };

    // Callback function for the Mutation Observer
    const callback = function(mutationsList) {
      for(let mutation of mutationsList) {
        if (mutation.type === 'childList') {
          console.log('A new element has been added:', mutation.addedNodes[0]);
        }
      }
    };

    // Instantiate and start the Mutation Observer
    const observer = new MutationObserver(callback);
    observer.observe(contentContainer, config);

    // Add new elements by clicking the button
    addButton.addEventListener('click', () => {
      const newElement = document.createElement('p');
      newElement.textContent = 'New dynamic element!
      contentContainer.appendChild(newElement);
    });
  </script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

This example shows how you can react to the addition of new elements with the mutation observer. Each time the user clicks on the button, a new <p> tag is added and output in the console log.

Monitor attributes like a pro 🕵️‍♂️

Sometimes you want to know exactly, when and how the attributes of a certain element change. Here is an example that you can also try out directly in Stackblitz:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Attribute observation</title>
</head>
<body>
  <div id="myElement" class="start">
    Observe my attribute
  </div>
  <button id="changeClassButton">Change class</button>

  <script>
    const element = document.getElementById('myElement');
    const changeClassButton = document.getElementById('changeClassButton');

    // Configure the Mutation Observer to watch for attribute changes
    const config = { attributes: true };

    // Callback function for the Mutation Observer
    const callback = function(mutationsList) {
      for(let mutation of mutationsList) {
        if (mutation.type === 'attributes') {
          console.log(`The attribute ${mutation.attributeName} was changed.`);
        }
      }
    };

    // Instantiate and start the Mutation Observer
    const observer = new MutationObserver(callback);
    observer.observe(element, config);

    // Change class by clicking the button
    changeClassButton.addEventListener('click', () => {
      element.classList.toggle('changed');
    });
  </script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

With this code, you can observe live how the class of an element changes. Each time you click on the button, the class changed will be added or removed and the mutation observer will report this in the console.

Tips-and-tricks-for-the-mutation-observer 🎯

  1. Avoid unnecessary observations: If you are only interested in certain changes (e.g.e.g. only childList), make sure that you only activate these in your configuration. This improves the performance of your application.
  2. Use the disconnect method: If you no longer need the observation, you should always deactivate the observer with observer.disconnect(). This prevents unnecessary memory consumption.
  3. Asynchronous processing: The mutation observer works asynchronously, which means that you can perform complex DOM manipulations without affecting the user experience.

Conclusion: The mutation observer is your friend! 💪

The Mutation Observer is an incredibly useful tool in modern web development. Whether you want to react to dynamic changes or monitor specific attributes, this API gives you the flexibility and control you need. With the examples shown here, you can get started right away and use the Mutation Observer in your projects.

Have you ever used the Mutation Observer? If so, what cool tricks have you discovered? Share your experiences in the comments and let's learn from each other!


If you like my posts, it would be nice if you follow my Blog for more tech stuff.

Top comments (0)