JavaScriptBrowser APIs

ResizeObserver

Calls a function every time an observed element’s size changes, no matter the cause of the change.

Returns
A new ResizeObserver object.
On this page

Example

#
JavaScript
const panel = document.querySelector('#panel')

const observer = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const border = Math.round(entry.borderBoxSize[0].inlineSize)
    const content = Math.round(entry.contentRect.width)
    console.log(`Panel: ${border} px, content: ${content} px`)
  }
})

observer.observe(panel)
Console
Panel: 200 px, content: 174 px

The first notification reports the size right after observation starts. contentRect doesn’t include padding and the border, which is why it’s 26 px narrower. Drag the bottom-right corner of the panel in the preview, and the console will show each change.

Definition and usage

#

ResizeObserver notifies you when a specific element’s size changes. The resize event on window only tells you about the window changing, but an element can change size for other reasons too: added content, a collapsed sidebar, or a class change. The observer catches every one of these cases.

The callback receives an array of ResizeObserverEntry objects. The contentRect field holds the width and height of the content area (without padding and border), while borderBoxSize and contentBoxSize give the sizes as arrays of objects with inlineSize (width, for regular horizontal text) and blockSize (height) fields.

If the element is displayed, the first call happens right after you start observing, so you learn the current size immediately. The observe() method adds an element, unobserve() removes it, and disconnect() ends the observation. The box option lets you choose which size to track, e.g. { box: "border-box" }.

Be careful about changing the observed element’s size directly inside the callback. The new size can’t be reported within the same frame, so the browser logs a "ResizeObserver loop completed with undelivered notifications" error, and the notification only arrives on the next frame. Put such changes off right away, e.g. with requestAnimationFrame().

Syntax

#
Syntax
new ResizeObserver(callback)

observer.observe(element)
observer.observe(element, { box })
observer.unobserve(element)
observer.disconnect()

Parameters

#
  • callback

    function (entries, observer)

    The function called after a size change. It receives an array of ResizeObserverEntry entries.
  • box

    optional, string (in observe())

    Which size to track: "content-box" (default), "border-box", or "device-pixel-content-box".

More examples

#
Layout that depends on an element’s width
JavaScript
const card = document.querySelector('#card')
const nextWidths = ['300px', '200px']

const observer = new ResizeObserver(([entry]) => {
  const width = Math.round(entry.borderBoxSize[0].inlineSize)
  card.classList.toggle('wide', width >= 280)
  console.log(`${width} px, wide layout: ${card.classList.contains('wide')}`)

  const next = nextWidths.shift()
  if (next) {
    setTimeout(() => {
      card.style.width = next
    })
  }
})

observer.observe(card)
Console
200 px, wide layout: false
300 px, wide layout: true
200 px, wide layout: false

We change the width automatically here to show further notifications. Each change is put off with setTimeout(), because changing the size directly inside the callback would trigger a loop error. In a real app the size changes on its own, e.g. after collapsing a sidebar.

Browser support

#

Widely available · since 2020

Works in all modern browsers, phones included. You can use it without worry.

  • Chrome
  • Edge
  • Firefox
  • Safari

Good practices

#
  • Reach for ResizeObserver instead of the resize event on window to react to an element’s size. An element can change size even while the window stays the same size.
  • Don’t change the observed element’s size directly inside the callback. Put the change off to the next frame, or only change things that don’t affect size, such as color.
  • If you only need to adjust styles to a container’s width, consider CSS container queries (@container). Then you don’t need JavaScript at all.

Related entries

#

Spotted a mistake or missing an example? Write to us.