Search code examples
javascriptcssresizeecmascript-6mutation-observers

Reacting to changes in the DOM: Mutation Observers, window.addEventListener("onresize", callback) or CSS alternatives?


I'm trying to figure out the best way to react to changes in the DOM.

I've read similar posts about this, such as this one and this one and neither of them make it explicitly clear when to use Mutation Observers and when to use window.addEventListener("onresize", callback). Are Mutation Observers more efficient than window.addEventListener("onresize", callback) even if the resize event is throttled?

I've included this under the CSS3 tag because it looks like there were, in 2012, some neat CSS tricks that triggered custom resize events and I was wondering if there have been any innovations since then.


Solution

  • Besides handling two entirely different and usually unrelated tasks, their timing is different.

    MutationObserver callback is executed as a microtask during current event when no changes have been painted on screen yet. Since Javascript is single-threaded, the callback execution blocks further DOM parsing and the entire JS engine, so you'd want to make it very fast (I'm afraid, most wrapper libraries aren't, because of their versatility) and avoid observing the entire document while a complex page is being loaded as the callback may be called hundreds of times with lots of addedNodes in each mutation.

    Events ("resize" event included) are added to the internal event queue and are processed when the current event queue has been completely processed and changes painted. For example, setTimeout(callback, 0), which creates a normal event task, may postpone the callback execution during a complex page load for 100-1000ms.

    So, use MutationObserver only if you really want to change something before it's painted to make your changes seamlessly integrated with the page. And of course, MutationObserver will only catch a change if an actual html attribute value has been changed or a node added/removed/changed, not just a calculated width based on CSS rules.