Under The Hood
frontend javascript ResizeObserver API (Level 1)

ResizeObserver: Depth-Order Measurement and Loop Limit Guard

Last updated
Prerequisites:
DOM layout and CSS box model
Understanding of the event loop and microtasks
  • resize-observer
  • layout
  • responsive
  • observers
  • loop-limit
  • measurement

Read at your depth

The practical view

ResizeObserver reports when an element's content-box or border-box size changes. const ro = new ResizeObserver((entries) => { for (const e of entries) { console.log(e.contentRect.width); } }); ro.observe(el);. Unlike window resize events, it observes individual elements and fires after layout settles, with an array of ResizeObserverEntry (target + contentRect + borderBoxSize/contentBoxSize). Useful for responsive components, canvas sizing, and text-overflow clamping. Call ro.disconnect() when done. Entries are delivered once per layout pass, batched; the API is built to avoid infinite feedback when you resize elements inside the callback.

The same idea in other frameworks

react equivalent
ResizeObserver is the modern replacement for window-resize-driven layout in React components (resize-detector, react-resize-observer).

Legacy vs modern

window.resize + manual measurement vs ResizeObserver

Window resize events miss element-level changes and need manual measurement; ResizeObserver observes the element itself with batched delivery after layout.

before → after
window.resize listener + manual measure
window.addEventListener('resize', () => { const w = el.offsetWidth; render(w); }); // ❌ OLD: only fires on window resize, forces layout read
ResizeObserver on the element
const ro = new ResizeObserver(entries => { render(entries[0].contentRect.width); });
ro.observe(el); // ✅ NEW: observes the element, batched, after layout

Interview gotchas

Context

This is the defining design question of ResizeObserver — interviewers want the loop-limit mechanism and the depth-order processing rule, not just 'don't resize in the callback'.

The mechanical answer

Resizing an element inside the callback triggers another layout pass and another delivery. To prevent infinite feedback, the spec defines a bounded resize processing loop: per rendering update, the engine runs at most two processing passes. If after the limit an observation still reports a size change, the engine does not keep looping; it queues an error event (a 'ResizeObserver loop limit exceeded' error delivered as a task) and stops further resizing for that cycle. Elements are processed in depth order (parents before children), so a parent resize that changes child sizes is delivered coherently. This deterministic guard is why the API is safe to use for self-resizing components (e.g. canvas fit-to-container).

Trap

The naive answer is 'just don't resize inside the callback'. Self-resizing is a legitimate pattern; the loop limit makes it bounded rather than infinite. Another trap: assuming the error is thrown synchronously — it is reported asynchronously as an error event, so it can be missed in tests. Candidates who explain the two-pass limit and the error event demonstrate understanding of the API's core contract.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.