Use 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.

In this tutorial, you will learn about basic usage of React Observer. You will also implement React Observer in your own front end code and test for browser support.

Prerequisites

To successfully complete this tutorial, you will need the following:

  • An understanding of HTML. The How To Build a Website with HTML series is a great place to start.
  • A basic knowledge of CSS. The How To Build a Website With CSS series can help you to achieve this.
  • An understanding of JavaScript for and forEach loops. To learn more about loops, visit this article called For Loops, For…Of Loops and For…In Loops in JavaScript. This article gives a thorough explanation of how forEach loops work.
  • An understanding of DOM Manipulation in JavaScript. Visit the Understanding the DOM — Document Object Model Series if you want to learn more about this topic.

Step 1 — Understanding Basic Usage of Resize Observe

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

const myObserver = new ResizeObserver(entries => {

});

 Copy

Within the callback function, you might iterate over the entries. With ResizeObserver instantiated, the observe function is called on the instance and the elements to observe are passed in:

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

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

 Copy

Each entry is assigned 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, the contentRect 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, you want log an observed element’s width and height when the element’s size changes, begin by creating a constant variable called myObserver and instantiating a new ResizeObserver:

const myObserver = new ResizeObserver(entries => {

});

 Copy

Inside of the callback function, iterate through every entry using forEach:

const myObserver = new ResizeObserver(entries => {
  entries.forEach(entry => {

  });
});

 Copy

Within the forEach loop, console.log the width and height of each entry using entry.contentRect.width and entry.contentRect.height respectively:

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

 Copy

To put myObserver to use, create an element called someEl using a DOM selector. Pass in someEl as the argument for myObserver.observe:

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);

 Copy

With an understanding of how Resize Observer is used, you can now move on to utilizing Resize Observer for a real world use case.

Step 2 — Demonstrating How Resize Observer is Used

Below is a 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:

Before using Resize Observer API, you’ll first need to create an index.html file:

touch index.html

 Copy

Inside of your HTML file, add the following code:index.html

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

 Copy

You’ll also need to add some styles to your HTML. Create a styles.css file and add the following CSS code to that file:styles.css

.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;
}

 Copy

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

Now, it’s time to move on to the JavaScript code. You can create an external JavaScript file or you can add <script> tags to your HTML file. First, create a DOM selector for all .box elements:

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

 Copy

Now instantiate a new ResizeObserver with a callback function that takes a parameter called entries:

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

const myObserver = new ResizeObserver(entries => {

});

 Copy

Create a for...of loop that will iterate through each entry in entries. Within the loop, create a constant variable infoEl that is set equal to entry.target.querySelector('.info'). This points to the .info element as the target:

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

const myObserver = new ResizeObserver(entries => {
  for (let entry of entries) {
    const infoEl = entry.target.querySelector('.info');
  }
});

 Copy

Create constant variables width and height which will be set to entry.contentRect.width and entry.contentRect.height respectively. Apply Math.floor to both to round down the values:

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);
  }
});

 Copy

Since you will be creating a gradient at an angle that changes with the width of your screen, create an angle variable that will be set equal to width / 360 * 100. Again, use Math.floor to round this value down:

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);
  }
});

 Copy

Create a constant called gradient that will hold the code for a linear gradient:

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), rgba(250,224,66,1))`;
  }
});

 Copy

With this gradient in place, you will need to set the background of the target entry to gradient using entry.target.style.background:

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), rgba(250,224,66,1))`;

    entry.target.style.background = gradient;
  }
});

 Copy

It would be helpful to see the values for the width and height on the screen as the change. Take the innerText of infoEl and set it to I'm ${width}px and ${height}px tall:

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), rgba(250,224,66,1))`;

    entry.target.style.background = gradient;

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

 Copy

The callback for ResizeObserver is complete. Now the myObserver function can be applied to boxes using a forEach loop:

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), rgba(250,224,66,1))`;

    entry.target.style.background = gradient;

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

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

 Copy

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

This is a working example of how Resize Observer can be used for responsive design. It’s important, though, to be aware of browser support for JavaScript features like this.

Step 3 — Evaluating Browser Support

Browser support for Resize Observer isn’t very extensive right now. Thankfully, there’s a polyfill that can be used in the mean time. The polyfill is based on the MutationObserver API.

You can visit Can I Use resizeobserver? to track support for this feature across the major browsers.

Conclusion

In this tutorial, you were able to understand what Reserve Observer can do, use it in your JavaScript code, and test for browser support.

Jasca
Author: Jasca

Share This Post
Have your say!
00

Customer Reviews

5
0%
4
0%
3
0%
2
0%
1
0%
0
100%
    Showing 2 reviews
  1. You Won’t Want To Miss This! 50 pcs medical surgical masks only $1.99 and N95 Mask $1.79 each.

    Only 10 orders left! Get yours here: pharmacyusa.online

    Enjoy,

    Use the Resize Observer JavaScript API – Treehoster

    0

    0

    You have already voted!

    Reply
  2. You Won’t Want To Miss This!

    Buy N95 Mask only $1.69 each and get 10 pcs of medical surgical masks for FREE.

    Limited Time Offer! + Fast Shipping! Get yours here: pharmacyusa.online

    Best Wishes,

    Use the Resize Observer JavaScript API – Treehoster

    0

    0

    You have already voted!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Thanks for submitting your comment!