A Look at the Resize Observer JavaScript API

Resize Observer is a new JavaScript API that’s very similar to other observer APIs like the Intersection Observer API. It allows for elements to be notified when their size changes.

The most frequent reason for an element’s size to change is when the viewport is resized or the device’s direction changes between portrait and landscape. Up until this point, we’ve had to rely on the global window.resize event to listen for resize events and check if certain elements have changed size. This can easily lead to performance problems due to the large amount of triggered event. In other words, using window.resize is often wasteful because it informs us of every viewport size change, not just when an element’s size actually changes.

There’s also another use case for the Resize Observer API that the window’s resize event can’t help us with: when elements are added or removed from the DOM dynamically, influencing the size of the parent element. This is more and more frequent with modern single-page apps.

Basic Usage

Using Resize Observer is as simple as instantiating a new ResizeObserver object and passing-in a callback function that receives the entries that are observed:

const myObserver = new ResizeObserver(entries => {
  // iterate over the entries, do something.
});

Then, we can call observe on our instance and pass-in an element to observe:

const someEl = document.querySelector('.some-element');
const someOtherEl = document.querySelector('.some-other-element');

myObserver.observe(someEl);
myObserver.observe(someOtherEl);

With each entry, we get an object with a contentRect and a target property. The target is the DOM element itself, and contentRect is an object with the following properties: width, height, x, y, top, right, bottom and left.

Unlike with an element’s getBoundingClientRect, contentRect’s values for width and height don’t include padding values. contentRect.top is the element’s top padding and contentRect.left is the element’s left padding.


If, for example, we want log an observed element’s width and height when the element’s size changes, we could do something like this:

const myObserver = new ResizeObserver(entries => {
  entries.forEach(entry => {
    console.log('width', entry.contentRect.width);
    console.log('height', entry.contentRect.height);
  });
});

const someEl = document.querySelector('.some-element');
myObserver.observe(someEl);

Simple Demo

Below is a simple demonstration to see the Resize Observer API in action. Try it out by resizing your browser window and notice how the gradient angle and text content only change when the element’s size is actually affected:


Let’s break down this simple demo. First, we start with some simple markup:

<div class="box">
  <h3 class="info"></h3>
</div>
<div class="box small">
  <h3 class="info"></h3>
</div>

And a touch of styles:

.box {
  text-align: center;
  height: 20vh;
  border-radius: 8px;
  box-shadow: 0 0 4px var(--subtle);

  display: flex;
  justify-content: center;
  align-items: center;
}

.box h3 {
  color: #fff;
  margin: 0;
  font-size: 5vmin;
  text-shadow: 0 0 10px rgba(0,0,0,0.4);
}

.box.small {
  max-width: 550px;
  margin: 1rem auto;
}

Notice how we don’t need to apply our gradient background to the .box element. The resize observer will be called once when the page first loads and our gradient will be applied then.

Now, the magic happens when we add the following JavaScript code:

const boxes = document.querySelectorAll('.box');

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
    const width = Math.floor(entry.contentRect.width);
    const height = Math.floor(entry.contentRect.height);

    const angle = Math.floor(width / 360 * 100);
    const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1) 50%, rgba(250,224,66,1) 50%)`;

    entry.target.style.background = gradient;

    infoEl.innerText = `I'm ${ width }px and ${ height }px tall`;
  }
});

boxes.forEach(box => {
  myObserver.observe(box);
});

Here we’re iterating over the entries in the observer’s callback using a for…of loop, but calling forEach on the entries would work just the same.

Notice how we also have to iterate over the elements that we can to observe and call observe on each element.

Browser Support

Browser support right now is pretty bad, with only Chrome 64+ supporting Resize Observer out of the box. Thankfully, there’s a polyfill we can use in the mean time. The polyfill is based on the MutationObserver API.

Browser Support

Can I Use resizeobserver? Data on support for the resizeobserver feature across the major browsers from caniuse.com.

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#