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 anElement
's content or border box, or the bounding box of anSVGElement
.
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.
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.
});
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);
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:
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>
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;
}
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)')
)
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)
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?
Correct, plus the maintainers get to use these instead of writing their own
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?
That's a great idea Dzhavat
This seems to be very useful, to watch individual events than event listener at root level.
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.