MutationObserver: MutationObserver() constructor

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

The DOM MutationObserver() constructor — part of the MutationObserver interface — creates and returns a new observer which invokes a specified callback when DOM events occur.

DOM observation does not begin immediately; the observe() method must be called first to establish which portion of the DOM to watch and what kinds of changes to watch for.

Syntax

js
new MutationObserver(callback)

Parameters

callback

A function which will be called on each DOM change that qualifies given the observed node or subtree and options.

The callback function takes as input two parameters:

  1. An array of MutationRecord objects, describing each change that occurred.
  2. The MutationObserver which invoked the callback. This is most often used to disconnect the observer using MutationObserver.disconnect().

See the examples below for more details.

Return value

A new MutationObserver object, configured to call the specified callback when DOM mutations occur.

Examples

Observing child elements

This example has buttons to add an <li> element to a list, and to remove the first <li> element from the list.

We use a MutationObserver to be notified about changes to the list. In the callback, we log additions and removals, and as soon as the list is empty, we disconnect the observer.

The "Reset example" button resets the example to its original state.

HTML

html
<button id="add">Add child</button>
<button id="remove">Remove child</button>
<button id="reset">Reset example</button>

<ul id="container"></ul>

<pre id="log"></pre>

CSS

css
#container,
#log {
  height: 150px;
  overflow: scroll;
}

#container li {
  background-color: paleturquoise;
  margin: 0.5rem;
}

JavaScript

js
const add = document.querySelector("#add");
const remove = document.querySelector("#remove");
const reset = document.querySelector("#reset");
const container = document.querySelector("#container");
const log = document.querySelector("#log");

let namePrefix = 0;

add.addEventListener("click", () => {
  const newItem = document.createElement("li");
  newItem.textContent = `item ${namePrefix}`;
  container.appendChild(newItem);
  namePrefix++;
});

remove.addEventListener("click", () => {
  const itemToRemove = document.querySelector("li");
  if (itemToRemove) {
    itemToRemove.parentNode.removeChild(itemToRemove);
  }
});

reset.addEventListener("click", () => {
  document.location.reload();
});

function logChanges(records, observer) {
  for (const record of records) {
    for (const addedNode of record.addedNodes) {
      log.textContent = `Added: ${addedNode.textContent}\n${log.textContent}`;
    }
    for (const removedNode of record.removedNodes) {
      log.textContent = `Removed: ${removedNode.textContent}\n${log.textContent}`;
    }
    if (record.target.childNodes.length === 0) {
      log.textContent = `Disconnected\n${log.textContent}`;
      observer.disconnect();
    }
    console.log(record.target.childNodes.length);
  }
}

const observerOptions = {
  childList: true,
  subtree: true,
};

const observer = new MutationObserver(logChanges);
observer.observe(container, observerOptions);

Result

Try clicking "Add child" to add list items, and "Remove child" to remove them. The observer callback logs additions and removals. As soon as the list is empty, the observer logs a "Disconnected" message and disconnects the observer.

The "Reset example" button reloads the example so you can try it again.

Specifications

Specification
DOM
# ref-for-dom-mutationobserver-mutationobserver①

Browser compatibility

desktop mobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
MutationObserver() constructor
Chrome – Full support
Chrome 18 (Release date: 2012-03-28)
prefix
prefix Implemented with the vendor prefix: WebKit
Chrome – Full support
Chrome 26 (Release date: 2013-03-26)
footnote Full support
Edge – Full support
Edge 12 (Release date: 2015-07-29)
footnote Full support
Firefox – Full support
Firefox 14 (Release date: 2012-07-17)
footnote Full support
Opera – Full support
Opera 15 (Release date: 2013-07-02)
footnote Full support
Safari – Full support
Safari 6 (Release date: 2012-07-25)
prefix
prefix Implemented with the vendor prefix: WebKit
Safari – Full support
Safari 7 (Release date: 2013-10-22)
footnote Full support
Chrome Android – Full support
Chrome Android 18 (Release date: 2012-06-27)
prefix
prefix Implemented with the vendor prefix: WebKit
Chrome Android – Full support
Chrome Android 26 (Release date: 2013-04-03)
footnote Full support
Firefox for Android – Full support
Firefox for Android 14 (Release date: 2012-06-26)
footnote Full support
Opera Android – Full support
Opera Android 14 (Release date: 2013-05-21)
footnote Full support
Safari on iOS – Full support
Safari on iOS 6 (Release date: 2012-09-10)
prefix
prefix Implemented with the vendor prefix: WebKit
Safari on iOS – Full support
Safari on iOS 7 (Release date: 2013-09-18)
footnote Full support
Samsung Internet – Full support
Samsung Internet 1 (Release date: 2013-04-27)
prefix
prefix Implemented with the vendor prefix: WebKit
Samsung Internet – Full support
Samsung Internet 1.5 (Release date: 2013-09-25)
footnote Full support
WebView Android – Full support
WebView Android 4.4 (Release date: 2013-12-09)
prefix
prefix Implemented with the vendor prefix: WebKit
WebView Android – Full support
WebView Android 4.4 (Release date: 2013-12-09)
footnote Full support
WebView on iOS – Full support
WebView on iOS 6 (Release date: 2012-09-10)
prefix
prefix Implemented with the vendor prefix: WebKit
WebView on iOS – Full support
WebView on iOS 7 (Release date: 2013-09-18)
footnote Full support

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
Requires a vendor prefix or different name for use.
Has more compatibility info.