All You Need to Know About Resize Observer in 6 Minutes
Introduction
When you’re working with responsive design, you’ll come across many use cases where you’d want to respond to changes in an element’s size. You can hack your way through it using media queries when the viewport’s size changes but what if you want to change your layout when a particular element changes in size? You go for the Resize Observer.
You can also watch a video version of this, available on youtube.
Usage
To use the ResizeObserver
API you simply create a new ResizeObserver
object instance using the constructor. This instance will have an observe
method that looks for changes to a specific element's size. A callback function set up inside the constructor then runs every time the size changes, providing access to the new dimensions and allowing you to do anything you like in response to those changes.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box {
background: lightblue;
height: 100px;
width: 100px;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
const box = document.getElementById("box")
const cb = (entries) => {
console.log(entries);
}
const observer = new ResizeObserver(cb)
observer.observe(box)
</script>
</body>
</html>
So let’s look at this simple example. Inside the HTML file, we create a simple div
tag with an id and some styles. Then inside the script
, we get a reference to the div
. We create a ResizeObserver
instance using the constructor and we pass in our callback function to it. This function will have access to each resize entry. You can also access the observer itself using a second argument if you want to but that’s completely optional. For now, we’ll just console.log
the resize entries inside this callback.
Finally, we’ll use the observe method on this observer
instance and we’ll pass the div
block inside this observer
. You can also pass in an options
object to this observer but for now, let’s run it as it is.
Now if you run this in the browser, you’ll find the div
block inside the viewport. Inside the console, you’ll also find an array with a resize entry. So the moment an observer starts observing a target, an entry will be registered at the beginning. Any subsequent entries will originate only from the target element. Now let’s take a look at the resize entry in the console.
Resize entry
Each entry is going to have some properties that’ll provide you with information related to the current size of the element.
borderBoxSize
andcontentBoxSize
will give you the latest sizes for borderBox and contentBox. The main difference between these two boxes is that borderBox will contain thepadding
and theborder
for the element along with its actual content. The content box will only have the main content.
This actually comes from the box model. So basically every element that you can think of will appear to be like a box. This box has 4 parts to it separated by their respective edges. There’s the actual content, the padding, the border, and finally the margin. SoborderBoxSize
will have the combination of these 4 areas.ContentBoxSize
will only have the content area.
ContentRect
will give you the info related to the size and position of your target element. ThiscontentRect
is of the typeDOMRect
just like we saw in the previous blog post on Intersection Observer. It’ll have the position properties like theleft
,right
,top
, andbottom
values along with size properties like itsheight
andwidth
.- Then we have the
devicePixelContentSizeBox
property which is an array of objects. Each object will have aninlineSize
and ablockSize
value. So essentially each block has awriting-mode
property. To put it simply, the writing mode is the direction in which the text flows inside an element. Just take a look at this example from w3schools and you’ll know what I mean.
So at any given point, both theblockSize
and theinlineSize
will either be the height or the width of the block depending upon the writing mode. If the writing mode is horizontal, then theblockSize
will be theheight
andinlineSize
will be thewidth
. It kinda makes sense becauseblock
elements by default take the entirewidth
of the container. So resizing ablock
element essentially means changing itsheight
which is also the reason whyinlineSize
represents thewidth
. Now if we change the writing mode to vertical, theblockSize
will be thewidth
and theinlineSize
will be theheight
.
You can actually try this out in the example. Just double the width of your block and set the writing mode to horizontal. You’ll see that when the writing mode is horizontal, theblockSize
acts as theheight
and theinlineSize
as thewidth
. Now if you change the writing mode to vertical, the values will be switched. TheblockSize
will now become thewidth
and theinlineSize
will be theheight
.
Now that we have a good understanding of these properties, let’s see why is it more than the original height and width. The reason is that the values insideinlineSize
andblockSize
deal with device pixels, not CSS pixels. So essentially every screen will have a bunch of pixels. A combination of those pixels forms a CSS pixel. The ratio between these two is called thedevicePixelRatio
. So if your device has a lot of pixels then the ratio goes up and so does the quality of the picture.
Now the reason why I bring up this ratio is that that is the differentiating factor between the dimensions that we set vs theinline
andblocksize
values. So inside the browser console, try to access thedevicePixelRatio
that’s present on the window object. If you multiply this by thewidth
or theheight
, you’ll get the correspondinginlineSize
orblocksize
values. - Finally, we have the
target
property which is the block that we’re observing.
Now that we’ve seen the resize entry let’s also quickly look at the options object that you can pass inside the observe
method.
Options object
So when observing an element, you can pass in an options object along with that element. Currently, this object only has 1 option which is the box
option. It lets you set the box model which the observer
will observe, for your target element. You can pass these values for the box
option.
content-box
, which is also the default option, when set, theobserver
will observe changes only for the original content of the element. If the padding, margin, or border of the element changes, it’s not going to trigger a callback.border-box
when set, the observer will trigger a callback anytime any property inside theborder-box
changes. So the padding, the content or the border if any one of these 3 values changes, theobserver
will trigger a callback.device-pixel-content-box
is the final option which again is pretty much the same ascontent-box
. The only difference is that any change in margin this time will also trigger a callback. To be honest, even I’m not sure why that’s the case but you’ll be using the first 2 options for the most part anyway. If you’re aware of this behavior and know what’s happening behind the scenes, do let me know in the comments.
Finally, just like any other observer, this one also has ways to disconnect
or unsubscribe
the observer
from its target to avoid memory leaks. If you read the previous blog post on Intersection observers, you’ll find that it’s exactly the same. We have a disconnect
method and an unobserve
method. The disconnect
will unsubscribe from all the target elements. So basically a single observer
can observe multiple targets. If I use the disconnect
method on the observer
, it’ll stop observing all those targets. Unobserve will only stop observing a specific target, so you are supposed to pass in the target element inside this method.
Conclusion
And that should cover a good chunk of this API. In conclusion, the Resize Observer API is a powerful tool for engineers looking to create responsive web apps. With its ability to detect changes in the size of elements on a web page, it provides an efficient and effective way to handle layout and content changes without the need for frequent polling or manual calculations.
You can also watch a video version of this, available on youtube.
Apart from this, if you have any doubts or suggestions, you can put them in the comments or get in touch with me on any one of my socials. Cheers!
More content at PlainEnglish.io.
Sign up for our free weekly newsletter. Follow us on Twitter, LinkedIn, YouTube, and Discord.
Interested in scaling your software startup? Check out Circuit.