What is a MutationObserver?
A MutationObserver lets you watch for changes in the DOM. Instead of polling or using deprecated events like DOMSubtreeModified, you can set up a callback that fires whenever something specific changes — like text content, attributes, or child elements.
const target = document.querySelector("#myDiv");
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
console.log("Change detected:", mutation.type);
});
});
observer.observe(target, {
childList: true,
subtree: true,
});
What Can You Observe?
You can configure the observer to watch for different types of changes:
observer.observe(target, {
childList: true, // Children added or removed
attributes: true, // Attributes changed
characterData: true, // Text content changed
subtree: true, // Watch all descendants, not just direct children
attributeOldValue: true, // Get the old attribute value
});
Practical Example
A common use case: watching for new elements added to a container, like a chat feed or infinite scroll.
const chatBox = document.querySelector("#chatMessages");
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1) {
console.log("New message:", node.textContent);
}
});
});
});
observer.observe(chatBox, { childList: true });
Try it Yourself →
Stopping the Observer
When you're done watching, call disconnect() to stop receiving notifications. You can also take a snapshot of pending changes with takeRecords().
// Stop observing
observer.disconnect();
// Get any pending changes
const pending = observer.takeRecords();
console.log("Pending changes:", pending.length);
Summary
MutationObserver is the modern, efficient way to react to DOM changes. Use it instead of deprecated mutation events. It's especially handy for working with frameworks that dynamically modify the DOM.