Observing Rendered DOM Nodes

Sam Thorogood has been looking into all kinds of changes that can happen to DOM Nodes:

This post will explain how to be notified when:

  • an element is added or removed from the DOM
  • the bounding box of an element changes (i.e., resizes)
  • an element moves around the page for any reason

Expect some ResizeObserver, IntersectionObserver, and MutationObserver sprinkled all over the post.

Observing rendered DOM nodes →

Related: On Twitter Denis Radin chimed in with his StyleObserver.js to track style changes.

Listen to your Web Pages

Always notice how in sci-fi movies the computers make those weird bleepy sounds?

Tom Hicks has created a JavaScript snippet that combines MutationObserver with AudioContext to recreate that effect.

Copy this into the console of any web page that is interactive and doesn’t do hard reloads. You will hear your DOM changes as different pitches of audio.


const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
const observer = new MutationObserver(function(mutationsList) {
  const oscillator = audioCtx.createOscillator()

  oscillator.connect(audioCtx.destination)
  oscillator.type = "sine"
  oscillator.frequency.setValueAtTime(
    Math.log(mutationsList.length + 5) * 880,
    audioCtx.currentTime,
  )

  oscillator.start()
  oscillator.stop(audioCtx.currentTime + 0.01)
})

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})

Try it on Facebook for example. It beeps all over the place 😆

There’s also an alternate version that mimics the effect as heard on TV better:


const audioCtx = new window.AudioContext();
const oscillator = audioCtx.createOscillator();
oscillator.connect(audioCtx.destination);
oscillator.type = "sine";

let numItems = 0

oscillator.frequency.setValueAtTime(
  1,
  audioCtx.currentTime
);

oscillator.start();

const observer = new MutationObserver(function (mutationsList) {
  numItems += mutationsList.length

  oscillator.frequency.setValueAtTime(
    Math.log(numItems + 1) * 440,
    audioCtx.currentTime
  );

  setTimeout(() => {
    numItems -= mutationsList.length
    if (numItems === 0) {
      oscillator.frequency.setValueAtTime(
          1,
          audioCtx.currentTime
        )
    } else {
        oscillator.frequency.setValueAtTime(
          Math.log(numItems + 1) * 440,
          audioCtx.currentTime
        )
    }
  }, 100)
});

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true
});

There’s also a browser extension available, but be warned: there’s no off switch (you’ll have to remove it to disable it)

Animate CSS Grid Layouts with animate-css-grid

In a new(ish) web-project I’m working on, I went all-in on CSS Grid. The website contains a page where one can filter the list of elements shown. To animate this filtering I used animate-css-grid, as other libraries typically used for this – e.g. Isotope – don’t play nice with CSS Grid.

Installation per NPM/Yarn:

yarn add animate-css-grid

Once imported use the wrapGrid function to let the library work its magic (using MutationObserver and FLIP animations)

import { wrapGrid } from animateCSSGrid

const grid = document.querySelector(".grid");
wrapGrid(grid);

animate-css-grid – Easy transitions for CSS Grid →

yett – A small webpage library to control the execution of (third party) scripts like analytics

In order to provide GDPR compliant consent-first-analytics (and other stuff), you can use yett:

Blocking execution of analytics script (until consent is given) can be done manually, but the problem is that analytics providers often provide minified code embeds that you have to include in your html as they are. If you want to exercise control over their execution, then you have to tamper with this minified JS yourself, which is complex and does not scale well if you load server 3rd party scripts.

Thus we invented yett. Just drop in the script and define a domain blacklist – yett will take care of the rest ✨.

Uses MutationObserver under the hood, thus is compatible with even IE11.

Beware though, as this might conflict with applications that rely heavily on document.createElement (like React):

This library monkey patches document.createElement. No way around this.

yett – Control the execution of (third party) scripts like analytics →