MutationObserver in a nutshell

Jaco Faber
PT SportSuite
Published in
3 min readNov 13, 2023

MutationObserver helps us watch for changes happening in the DOM. This simple overview will show you how to use MutationObserver.

How do we use MutationObserver?

The first step is to obtain the element we want to watch for changes.

const elementToObserve = document.querySelector("selector");

Once we have the element we want to watch for changes, we need to set up the callback to execute when any changes occur. The MutationObserver will pass our callback two parameters:

  1. A list of changes that occurred. These changes are defined as MutationRecord instances.
  2. The MutationObserver instance that executed our callback. This is useful for stopping the MutationObserver from inside our callback.

The MutationRecord that represents a change contains a few helpful parameters:

  • type: The type of change observed, which can be:
    - attributes: When any attribute on the element was changed, for example, if the class attribute changed, added, or removed.
    - characterData: We will only see this type if the element we are watching is a CharacterData node.
    - childList: When the tree of child nodes of the element changed, for example, if a child element was added or removed. This will also be the type we will see when the inner content of an element changes, for example, if the text of an h1 element changes.
  • addedNodes: Contains a list of nodes that were added. This list will be empty if no nodes were added.
  • removedNodes: Contains a list of nodes that were removed. This list will be empty if no nodes were removed.
  • attributeName: Contains the name of the attribute that changed. This will be null if no attributes were changed.
  • attributeNamespace: Contains the namespace of the attribute that changed. This will be null if no attributes were changed.
  • previousSibling: Contains the previous sibling element of the node that was added or removed.
  • nextSibling: Contains the next sibling element of the node that was added or removed.
  • oldValue:
    - If an attributes change was observed, this will be the old value of the attribute.
    - If a characterData change was observed, this will be the old data of the node.
    - If a childList change was observed, this will be null.
  • target:
    - If an attributes change was observed, this will be the element that was changed.
    - If a characterData change was observed, this will be the characterData node.
    - If a childList change was observed, this will be the element whose children were changed.
const callback = (changes, observer) => {
for (const mutation of changes) {
console.log(`🕵 '${mutation.type}' change was observed!`, mutation);
}
};

Now that we have our element to watch and our callback ready, we can instantiate our MutationObserver instance and start watching for changes. We need to tell the observer what changes to look out for, so when we start the observer, we pass an object along with the element we want to watch. The options we can pass are:

  • subtree: If this is set to true, all the child elements rooted in the element we are watching will also be observed.
  • childList: If the observer should watch out for elements being added or removed.
  • attributes: If the observer should watch out for any attributes being changed.
  • attributeFilter: Here we can pass a list of attribute names the observer should be watching.
  • attributeOldValue: If this is set to true, the observer will record the previous value of changed attributes.
  • characterData: If the observer should watch out for changes to character data nodes inside the element it’s watching.
  • characterDataOldValue: If this is set to true, the observer will record the previous value of changed characterData nodes.
const mutationObserver = new MutationObserver(callback);
mutationObserver.observe(elementToObserve, {
attributes: true,
childList: true,
subtree: true
});

To stop the observer, we can call the disconnect method. We can also do this from inside our callback function if we need to.

mutationObserver.disconnect();

Browser Support

MutationObserver is supported by all modern browsers.

In conclusion, learning how to use MutationObserver is a great addition to any web developer’s arsenal. Happy coding!

--

--

Jaco Faber
PT SportSuite

Head of Product Development at PT SportSuite - AWS, PHP, JavaScript, Flutter