
How JS Works: Tracking Changes in the DOM Using MutationObserver
- Transfer
Today, in the translation of the tenth material from the series devoted to the features of the work of JavaScript mechanisms, we will talk about how to track changes in the DOM using the MutationObserver API.
The client parts of web applications are becoming more complex, require more system resources. This happens for various reasons, in particular due to the fact that such applications need advanced interfaces, due to which their capabilities are revealed, and due to the fact that they have to perform complex calculations on the client side.

All this leads to a complication of the task of monitoring the state of application interfaces in the process of their life cycle. This task becomes even larger if we are talking about developing something like a framework or even a regular library, when, for example, you need to react to what is happening with the page and perform some actions that depend on the DOM.
MutationObserver is a Web API provided by modern browsers and designed to detect changes in the DOM. Using this API, you can observe the addition or removal of DOM nodes, the change in the attributes of elements, or, for example, the change in the text of text nodes. Why is this needed?
There are many situations in which an API

Browser-based text editor The
above are just a few of the situations in which features
Use
The created object has three methods:
Here's how to enable change monitoring:
Now suppose the DOM has the simplest element
Using jQuery, you can remove the attribute
Due to the fact that we started monitoring changes by calling

MutationRecord Object
Here you can see mutations caused by the removal of the attribute
And finally, in order to stop monitoring the DOM after the work is completed, you can do the following:
The API

MutationObserver Support
It is worth noting that the DOM change observation mechanism that it offers
The simplest and most straightforward way to track DOM changes is to poll. Using the method,
The MutationEvents API was introduced in 2000. Despite the fact that this API allows you to solve the tasks assigned to it, mutation events are raised after each DOM change, which, again, leads to performance problems. The API

MutationEvents Support
In fact, an alternative
In order to use this method, we first need the parent element, for which we want to observe the addition of new nodes:
To organize monitoring of adding nodes to it, you need to configure a sequence of key frames of CSS animation that will start when you add a node:
After creating keyframes, the animation should be applied to the elements that need to be watched. Pay attention to the duration of the animation. It is very small, so the animation is almost invisible.
Here we add animation to all descendant nodes of the element
Now we need a JS function that will play the role of an event handler. Inside the function, first of all, it is necessary to perform a check
Now add an event handler to the parent element. Different browsers do this differently:
This is how CSS animations work in various browsers.

Support for CSS animations in various browsers
We looked at APIs
The author of the material notes that it
Previous parts of the series of articles:
Part 1:How JS works: an overview of the engine, run-time mechanisms, call stack
Part 2: How JS works: about the V8 internal device and code optimization
Part 3: How JS works: memory management, four types of memory leaks and how to deal with them
Part 4: How it works JS: event loop, asynchrony, and five ways to improve your code with async / await
Part 5: How JS: WebSocket and HTTP / 2 + SSE work. What to choose?
Part 6: How JS Works: Features and Scope of WebAssembly
Part 7: How JS Works: Web Workers and Five Usage Scenarios
Part 8: How JS Works: Service Workers
Part 9: How JS Works: Web Push Notifications
Dear readers! Do you use MutationObserver in your projects?

The client parts of web applications are becoming more complex, require more system resources. This happens for various reasons, in particular due to the fact that such applications need advanced interfaces, due to which their capabilities are revealed, and due to the fact that they have to perform complex calculations on the client side.

All this leads to a complication of the task of monitoring the state of application interfaces in the process of their life cycle. This task becomes even larger if we are talking about developing something like a framework or even a regular library, when, for example, you need to react to what is happening with the page and perform some actions that depend on the DOM.
[Advise reading] The other 19 parts of the cycle
Part 1: Overview of the engine, runtime mechanisms, call stack
Part 2: About the V8 internal device and code optimization
Part 3: Memory management, four types of memory leaks and their fight
Part 4: Event loop, asynchronism and five ways to improve the code using async / await
Part 5: WebSocket and HTTP / 2 + SSE. What to choose?
Part 6: Features and scope of WebAssembly
Part 7: Web workers and five scenarios for their use
Part 8: Service workers
Part 9: Web push notifications
Part 10: Tracking changes in the DOM using MutationObserver
Part 11:Web page rendering engines and tips for optimizing their performance
Part 12: Network browser subsystem, optimizing its performance and security
Part 12: Network browser subsystem, optimizing its performance and security
Part 13: Animation using CSS and JavaScript
Part 14: How JS works: abstract syntax tree parsing and optimization
Part 15: How does JS: classes and inheritance, transpilyatsiya in Babel and TypeScript
Part 16: How does JS: storage systems
Part 17: How does JS: Shadow DOM technology and ee components
Part 18:How JS Works: WebRTC and P2P Communication Mechanisms
Part 19: How JS Works: User Elements
Part 2: About the V8 internal device and code optimization
Part 3: Memory management, four types of memory leaks and their fight
Part 4: Event loop, asynchronism and five ways to improve the code using async / await
Part 5: WebSocket and HTTP / 2 + SSE. What to choose?
Part 6: Features and scope of WebAssembly
Part 7: Web workers and five scenarios for their use
Part 8: Service workers
Part 9: Web push notifications
Part 10: Tracking changes in the DOM using MutationObserver
Part 11:Web page rendering engines and tips for optimizing their performance
Part 12: Network browser subsystem, optimizing its performance and security
Part 12: Network browser subsystem, optimizing its performance and security
Part 13: Animation using CSS and JavaScript
Part 14: How JS works: abstract syntax tree parsing and optimization
Part 15: How does JS: classes and inheritance, transpilyatsiya in Babel and TypeScript
Part 16: How does JS: storage systems
Part 17: How does JS: Shadow DOM technology and ee components
Part 18:How JS Works: WebRTC and P2P Communication Mechanisms
Part 19: How JS Works: User Elements
Overview
MutationObserver is a Web API provided by modern browsers and designed to detect changes in the DOM. Using this API, you can observe the addition or removal of DOM nodes, the change in the attributes of elements, or, for example, the change in the text of text nodes. Why is this needed?
There are many situations in which an API
MutationObserver
can be very helpful. For instance:- You need to notify the user of the web application that some changes have occurred on the page with which he is working.
- You are working on a new interesting JS framework that dynamically loads JavaScript modules based on DOM changes.
- Perhaps you are working on a WYSIWYG editor and are trying to implement undo and redo functionality. Using the API
MutationObserver
, you will at any time know what changes have occurred on the page, which means that you can easily undo them.

Browser-based text editor The
above are just a few of the situations in which features
MutationObserver
may be useful. In fact, there are many more.How to use MutationObserver
Use
MutationObserver
in web applications is quite simple. You need to create an instance MutationObserver
by passing a function to the appropriate constructor, which will be called every time changes occur in the DOM. The first argument to the function is a collection of all the mutations that occurred in a single package. For each mutation, information is provided on its type and on the changes that it represents.var mutationObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});
The created object has three methods:
- The method
observe
starts the DOM change tracking process. It takes two arguments - the DOM node to watch for, and the object with the parameters. - The method
disconnect
stops monitoring changes. - The method
takeRecords
returns the current queue of the instanceMutationObserver
, after which it clears it.
Here's how to enable change monitoring:
// Запускаем наблюдение за изменениями в корневом HTML-элементе страницы
mutationObserver.observe(document.documentElement, {
attributes: true,
characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
});
Now suppose the DOM has the simplest element
div
: Simple div
Using jQuery, you can remove the attribute
class
from this element:$("#sample-div").removeAttr("class");
Due to the fact that we started monitoring changes by calling
mutationObserver.observe(...)
it first and the function that responds to the arrival of a new change package displays the received data to the console, we will see the contents of the corresponding MutationRecord object in the console :
MutationRecord Object
Here you can see mutations caused by the removal of the attribute
class
. And finally, in order to stop monitoring the DOM after the work is completed, you can do the following:
// Прекратим наблюдение за изменениями
mutationObserver.disconnect();
MutationObserver support in various browsers
The API
MutationObserver
is widely supported in browsers:
MutationObserver Support
Alternatives to MutationObserver
It is worth noting that the DOM change observation mechanism that it offers
MutationObserver
was not always available to developers. What did they use before they appeared MutationObserver
? Here are a few options:- Polling.
- The mechanism
MutationEvents
. - CSS animation.
▍ Survey
The simplest and most straightforward way to track DOM changes is to poll. Using the method,
setInterval
you can schedule periodic execution of a function that checks the DOM for changes. Naturally, using this method significantly reduces the performance of web applications.▍MutationEvents
The MutationEvents API was introduced in 2000. Despite the fact that this API allows you to solve the tasks assigned to it, mutation events are raised after each DOM change, which, again, leads to performance problems. The API
MutationEvents
is now deprecated and soon modern browsers will no longer support it.
MutationEvents Support
▍CSS animation
In fact, an alternative
MutationObserver
in the form of CSS-animations can seem a bit strange. And here is the animation? In general, the idea here is to create an animation that will be called after the element is added to the DOM. When the animation starts, an event will be triggered animationstart
. If you assign a handler for this event, you can find out the exact time the new item was added to the DOM. In this case, the animation execution time should be so short that it is almost invisible to the user. In order to use this method, we first need the parent element, for which we want to observe the addition of new nodes:
To organize monitoring of adding nodes to it, you need to configure a sequence of key frames of CSS animation that will start when you add a node:
@keyframes nodeInserted {
from { opacity: 0.99; }
to { opacity: 1; }
}
After creating keyframes, the animation should be applied to the elements that need to be watched. Pay attention to the duration of the animation. It is very small, so the animation is almost invisible.
#container-element * {
animation-duration: 0.001s;
animation-name: nodeInserted;
}
Here we add animation to all descendant nodes of the element
container-element
. When the animation ends, the corresponding event is fired. Now we need a JS function that will play the role of an event handler. Inside the function, first of all, it is necessary to perform a check
event.animationName
in order to make sure that this is exactly the animation that interests us.var insertionListener = function(event) {
// Убедимся в том, что это именно та анимация, которая нас интересует
if (event.animationName === "nodeInserted") {
console.log("Node has been inserted: " + event.target);
}
}
Now add an event handler to the parent element. Different browsers do this differently:
document.addEventListener("animationstart", insertionListener, false); // standard + firefox
document.addEventListener("MSAnimationStart", insertionListener, false); // IE
document.addEventListener("webkitAnimationStart", insertionListener, false); // Chrome + Safari
This is how CSS animations work in various browsers.

Support for CSS animations in various browsers
Summary
We looked at APIs
MutationObserver
and alternative ways to monitor DOM changes. It should be noted that it MutationObserver
has many advantages over these alternatives. In general, we can say that this API is able to report any changes that may occur in the DOM, that it is well optimized, giving information about the changes collected in packages. In addition, the API MutationObserver
enjoys the support of all major modern browsers, and there are polyfills for it based on MutationEvents
. The author of the material notes that it
MutationObserver
occupies a central place in the SessionStack library , which is aimed at organizing the collection of data on what is happening with web pages. Previous parts of the series of articles:
Part 1:How JS works: an overview of the engine, run-time mechanisms, call stack
Part 2: How JS works: about the V8 internal device and code optimization
Part 3: How JS works: memory management, four types of memory leaks and how to deal with them
Part 4: How it works JS: event loop, asynchrony, and five ways to improve your code with async / await
Part 5: How JS: WebSocket and HTTP / 2 + SSE work. What to choose?
Part 6: How JS Works: Features and Scope of WebAssembly
Part 7: How JS Works: Web Workers and Five Usage Scenarios
Part 8: How JS Works: Service Workers
Part 9: How JS Works: Web Push Notifications
Dear readers! Do you use MutationObserver in your projects?
