JavaScript Resize Observer Ultimate Guide
January 31, 2022
Resize Observer is one of 3 observer based JavaScript APIs with the other two being Intersection Observer and Mutation Observer. While I do not think Resize Observer is as useful as something like Intersection Observer it is still useful to know. Right now Resize Observer is the only way to detect element size changes and makes changing content/styles on a page based on resizing so much easier.
If you prefer to learn visually, check out the video version of this article.
Your First Resize Observer
Creating a Resize Observer is actually quite simple since all you need to do is pass a function to the ResizeObserver
constructor.
const observer = new ResizeObserver(entries => {
console.log(entries)
})
In the above example we created a brand new Resize Observer and in the function we passed to it we are just logging out the entries
parameter. This entries
parameter is the only argument that the function accepts and it just outputs the information related to each element when it changes size. That may sound confusing but let’s take a look at a simple example.
const observer = new ResizeObserver(entries => {
entries.forEach(entry => {
const isSmall = entry.contentRect.width < 150
entry.target.style.backgroundColor = isSmall ? "blue" : "orange"
})
})
observer.observe(document.getElementById("test"))
In the above code we are calling the observe
method on our Resize Observer and telling it to observe size changes for the element with the id test. These size changes can occur in many ways such as the window size changing, elements being added/removed from the page, user interaction, and much more. Essentially, any time an element you are observing changes size it will trigger the function passed to ResizeObserver
.
In our code we are looping through all the elements in the entries
array. This array just lists all the elements we are observing that have had their size change. We are then looping through those entries and for each one we are checking the contentRect
property. This property contains information such as the width, height, top, left, bottom, right, etc. of our element. Finally, we are using the target
property of our entry to get the current element that is being observed and changing its background to the appropriate color.
Resize Observer Options
Unlike the other observer APIs, Resize Observer has very limited options you can configure. There is actually only one option you can configure which is the box model that is used to determine resize changes. This option is passed as a second parameter to the observe
function.
Box
The box
property allows you to change which box model is used to determine size changes. By default the content-box
is used, but you can also use the border-box
, and the device-pixel-content-box
. The border-box
option takes into account things like border and padding changes, while the content-box
only includes the actual content of the element. The device-pixel-content-box
is similar to the content-box
option but it takes into account the actual pixel size of the device it is rendering too. This means that the device-pixel-content-box
will change at a different rate than the content-box
depending on the pixel density of the device.
const observer = new ResizeObserver(changeColor)
observer.observe(document.getElementById("test"), { box: "border-box" })
Resize Observer Entry
The entries array in the Resize Observer callback contains lots of useful information about the element. The most important properties are the target
and contentRect
since they tell you the majority of the information you need to know about which element is resizing and what its new size is. There are also 3 additional properties that all provide additional information about the width/height of the element.
These properties are borderBoxSize
, contentBoxSize
, and devicePixelContentBoxSize
, and they perfectly line up with the 3 different box model types discussed earlier. Each of these properties will be an array that will almost always contain just one value which is an object with a blockSize
and inlineSize
property. The blockSize
property defines the height of the element while the inlineSize
defines the width. If the writing mode of your document is vertical, though, the blockSize
will define the width while the inlineSize
will define the height. Each of these values will be calculated for the box size specified by the property being accessed.
const observer = new ResizeObserver(entries => {
entries.forEach(entry => {
console.log(entry.borderBoxSize[0].blockSize)
console.log(entry.contentBoxSize[0].blockSize)
console.log(entry.devicePixelContentBoxSize[0].blockSize)
})
}))
observer.observe(document.getElementById("test"))
Advanced Resize Observer
This covers all the basic use cases and options for Resize Observers, but there are a few additional things you should know.
Second Callback Parameter
The callback you pass to new Resize Observers actually has two parameters. The first parameter is the entries
parameter we have talked a bunch about. The second parameter is simply the observer that is observing the changes.
const observer = new ResizeObserver((entries, o) => {
console.log(o === observer)
// True
})
This parameter is useful when you need to do something with the observer from within the callback since you may not always have access to the observer variable from the callback depending on where the callback is defined.
Unobserve and Disconnect
It is important to stop observing elements when they no longer need to be observed, such as after they are removed from the page in order to avoid memory leaks or performance issues. This can be done with the unobserve
method or the disconnect
method which are both methods on the Resize Observer. The unobserve
method takes a single element as its only parameter and it stops observing that single element. The disconnect
method takes no parameters and will stop observing all elements.
new ResizeObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.contentRect.width < 150) {
observer.unobserve(entry.target)
entry.target.remove()
}
})
})
Conclusion
The Resize Observer is a very simple API to understand and has limited use cases, but it can be incredibly powerful in specific situations.
If you want to learn more about the other observer based APIs you can check out my Intersection Observer Ultimate Guide.