DOM mutation events replacement

Since DOM mutation is marked as deprecated by the w3c (see, is there an (fast) alternative way to detect attribute modification in the DOM ?


As far as I know there is no alternative (yet) so you are stuck with DOMAttrModified which is only supported in Firefox and Opera. In IE you have the onpropertychanged event but there is no way to get similar functionality in Chrome/Safari. There are a number of things you could do depending on what you are trying to accomplish and the browsers you are targetting:

  • define getters and setters to the attributes you want to monitor
  • override methods like document.createAttribute, attributes.setNamedItem, ...

I've been working on a cross-browser solution myself but without much success. You should stay away from mutation events all together since they are not cross-browser and very slow. There are good reasons why they are deprecated. If you want to learn more read this:

The reason that mutation events was deprecated was because of huge performance issues.

The replacement is Mutation Observers, look at and

Information about mutations is delivered to observers as an ordered sequence of MutationRecords, representing an observed sequence of changes that have occurred

Sample usage:

    var observer = new MutationObserver(function(mutationRecords) {
    // Handle mutations

     {  // options:
     subtree: true,  // observe the subtree rooted at myNode
     childList: true,  // include information childNode insertion/removals
     attribute: true  // include information about changes to attributes within the subtree

This is supported in Chrome 18 and Firefox and Webkit nightly builds. Firefox 14 will also be supporting this feature.

A great replacement for the deprecated DOM* events is animationStart in conjunction with CSS Animations. David Walsh writes about the method.

First, set up the keyframes and apply it to the elements you'd like to listen for (don't forget the vendor prefixes!):

@keyframes nodeInserted {  
  from { clip: rect(1px, auto, auto, auto); }
  to { clip: rect(0px, auto, auto, auto); }  

#parentElement > li {
  animation-duration: 0.001s;
  animation-name: nodeInserted;

Next, add the listener:

var insertListener = function(event){
  if (event.animationName == "nodeInserted") {
    // This is the debug for knowing our listener worked!
    // is the new node!
    console.warn("Another node has been inserted! ", event,;
document.addEventListener("animationstart", insertListener, false); // standard + firefox
document.addEventListener("MSAnimationStart", insertListener, false); // IE
document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari

Ta-da! Here is David's demo. It works great for me on a Chrome extension that adds Facebook pictures to Google Voice (see content.css and injected.js).

A year later, there are the new and shiny Mutation Observers from DOM Level 4 (follow the links there, they explain a lot!). Where a Mutation Event fired a thousand times, MutationObserver fires only once with all the modifications contained and accessible.

Works for (as of 2017/03):

  • Firefox 14+
  • IE 11
  • Edge
  • Opera 15+
  • Chrome 26+ (18 till 25 prefixed, window.WebKitMutationObserver)
  • Safari 6.0 (prefixed, window.WebKitMutationObserver)

Need Your Help

does animateWithDuration:animations: block main thread?

iphone objective-c cocoa-touch animation multithreading

I have connected the two methods below to separate buttons in my UI but have noticed that after pressing the "VERSION 1" button that I could not press the button again until the animation duration ...

How to write css fallbacks for vh vw

css css3 fallback viewport-units

Can anyone explain how fallbacks work in CSS? I am trying to set it up for vh and vw and clearly I am not getting it...