DEV Community

Yaser Adel Mehraban
Yaser Adel Mehraban

Posted on • Originally published at yashints.dev

Let's get to know the ResizeObserver πŸ‘‹πŸΌ

Resize Observer API is another great JavaScript API which lets you get notified when the size of an element changes. Think window.onresize but on element level.

The what

The most common case when the size of an element could change is when the viewport is resized. Or in terms of mobile device the orientation changes.

Prior to ResizeObserver you would have to hook into window.onresize or use window.resize to be able to figure out whether an element's size has changed or not. This was very inefficient since it would trigger so many events.

Another scenario where this API can come handy is when you add/remove an element dynamically, in which case the size of the parent changes and not the viewport.

The ResizeObserver interface reports changes to the dimensions of an Element's content or border box, or the bounding box of an SVGElement.

The content box is the box in which content can be placed, meaning the border box minus the padding and border width. The border box encompasses the content, padding, and border.

Box model

Enough talking, shoe me the code πŸ˜‰

In its simplest form, you can use ResizeObserver by just instantiating a new instance of the API and pass a call-back to it.

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

By itself, this wouldn't help much, however if you call the observe method on the instance and give it an element, it will start capturing it's size changes and calls your call-back function.

const myEl = document.querySelector('.my-element');

myObserver.observe(myEl);
Enter fullscreen mode Exit fullscreen mode

Now whenever my element's size changes, it will trigger the call-back and voila.

call-back input object

When you pass a call-back to the constructor of the API, what you get is an array of objects which look like below:

ResizeObserver Entry

As you can see, the object you get has two properties, contentRect and target. Target is obvious, it's the DOM element itself. The width and height values on the contentRect don't include the padding unlike the element's getBoundingClientRect.

Demo

You can do a lot with this API, from changing the font size based on the element's size to change the styling when the size changes. Below is one where I'm changing the border radios based on element's size. Resize your window and see what happens 😎.

Demo explained

The demo is not that complex, we have a div which is got two children:

<div class="boxes">
  <div class="box"></div>
  <div class="box"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

We add a bit of styling so we can see the changes:

.boxes {
  display: flex;
  flex-wrap: wrap;
  width: 40vw;
  margin-bottom: 50px;
}
.box {
  height: 200px;
  flex-shrink: 1;
  flex-grow: 1;
  margin: 10px;
  box-sizing: border-box;
  border: 3px solid black;
}
Enter fullscreen mode Exit fullscreen mode

Once we're done, we add our little snippet to get the observer notify us of changes:

const ro = new ResizeObserver(entries => {
  for (let entry of entries) {
    entry.target.style.borderRadius =
      Math.max(0, 250 - entry.contentRect.width) +
      'px'
  }
})
console.log('horay');
// Only observe the 2nd box
ro.observe(
  document.querySelector('.box:nth-child(2)')
)
Enter fullscreen mode Exit fullscreen mode

In the call-back, we simply change the border radios based on width of the element, and voila.

Browser support

Browser support is there for most major browsers, we have Chrome 64+, Firefox 69+, Microsoft Edge 76, and Safari 13-TP supporting the API, but a poor support on mobile browsers.

Have fun exploring the API and do some cool stuff with it 😍.

Top comments (6)

Collapse
 
cvanpoelje profile image
cvanpoelje

Very nice to see that some of these concepts I love about our favorite frameworks are now also introduced to JavaScript itself. Correct me if i'm wrong but these are the type of tools we need to get better encapsulation within vanilla JavaScript right?

Collapse
 
yashints profile image
Yaser Adel Mehraban

Correct, plus the maintainers get to use these instead of writing their own

Collapse
 
dzhavat profile image
Dzhavat Ushev

I noticed that Firefox added support for this API in its latest version, so I wanted to write about it as well :)

You've explained it quite good. Do you think adding a section for how to feature detect it will be useful?

Collapse
 
yashints profile image
Yaser Adel Mehraban

That's a great idea Dzhavat

Collapse
 
hozefaj profile image
Hozefa

This seems to be very useful, to watch individual events than event listener at root level.

Collapse
 
cvanpoelje profile image
cvanpoelje

Listeners at root level will cost your app a lot more, especially when you use a lot of them. With the ability to apply them on children instead of root it must be easier to stop the Event listener from listening when the element no longer exists to prevent memory leaks.