Why observe an element instead of the window?
A window resize event tells you that the viewport changed. It does not tell you whether a particular element changed size. A panel can become narrower when a sidebar opens, a parent grid changes, or neighboring content takes up more space, all without a window resize. ResizeObserver watches the element itself, making it useful when JavaScript behavior depends on the space a component actually has.
For presentation changes alone, consider CSS first. Flexible layouts and container queries can often adapt a component without JavaScript. ResizeObserver is useful when a size change must also trigger behavior, such as updating a canvas drawing or changing how many items a script renders.
Observe a panel in the browser
The following example is for JavaScript running in a browser with ResizeObserver and requestAnimationFrame available. Assume the page already has an element with the ID panel and a separate text element with the ID panel-status. The status element should sit outside the panel’s measured layout so changing its text does not change the panel’s width.
const panel = document.querySelector("#panel"); const status = document.querySelector("#panel-status"); if (panel && status && "ResizeObserver" in window) { let frame = 0; const observer = new ResizeObserver(entries => { const width = entries[0].contentRect.width; cancelAnimationFrame(frame); frame = requestAnimationFrame(() => { status.textContent = width < 360 ? "Compact panel" : "Roomy panel"; }); }); observer.observe(panel); // When this part of the interface is removed: // cancelAnimationFrame(frame); // observer.disconnect(); }
Calling observe registers the panel. The callback receives an array of entries because one observer can watch multiple elements. Each entry identifies its element through target and reports measurements through properties such as contentRect. The callback is also expected to run when observation begins, so a separate initial width check is usually unnecessary. The 360-pixel threshold here is only an example; choose a threshold based on the component’s actual layout needs.
Choose the measurement that matches the task
In the example, contentRect.width is a straightforward way to read the observed element’s content-box width. The content box excludes padding and borders. If those edges matter, ResizeObserver can also report box sizes, including borderBoxSize. You can request a box when observing an element, for example with observer.observe(panel, { box: "border-box" }), and then read the corresponding size information from the entry.
Be deliberate about what you measure. If a drawing must fit inside an element’s content area, content-box dimensions may be appropriate. If your decision concerns the component’s visible outer boundary, border-box dimensions may be a better match. For responsive behavior, using the observed element’s width is generally more relevant than guessing its size from window.innerWidth.
Avoid layout feedback loops
A ResizeObserver callback runs in response to layout changes. If the callback changes the observed element’s size, that change may trigger another callback. For example, adding padding whenever a panel becomes narrow could make it wide again, causing the script to switch repeatedly. Such feedback can produce unstable behavior rather than a useful responsive interface.
Keep measurement and updates separate where possible. The example reads the panel’s width, then schedules a text update for the next animation frame; it also cancels a pending update if a newer measurement arrives first. Scheduling a write can help avoid an immediate read-and-write cycle, but it does not fix a design that continually changes the observed element’s dimensions. If you do change a layout-related state, update it only when the desired state differs from the current one, and check that the two states do not force each other to alternate.
Clean up and plan a fallback
An observer continues watching until you call unobserve for a particular element or disconnect to stop watching everything registered with it. When a component is removed, disconnect its observer and cancel any pending animation frame. This matters especially in interfaces that repeatedly create and remove panels: cleanup prevents callbacks from continuing after their work is no longer needed.
If ResizeObserver is unavailable in the environment you support, let the layout remain usable with CSS rather than assuming the script will run. You can then decide whether that interface needs an additional fallback for its JavaScript behavior. Test by resizing the panel through its parent layout as well as by resizing the browser window; the first case is the reason to use an element observer in the first place.



