ResizeObserver is a safe place to read scrollWidth/clientWidth

Avoid forced synchronous layout and safely read an element's size.

A common performance issue in web apps is forced synchronous layout: reading the size of an element and forcing the browser to immediately and synchronously undergo layout and style calculations in order to figure out the size.

This can be worked around by using a ResizeObserver. This API lets you receive a callback whenever the browser changes the size of an observed element. When the callback is invoked, the size of the element has just been calculated. This means you can safely read properties like .offsetWidth, .scrollWidth, and .clientWidth in addition to the properties provided by the ResizeObserver callback like .borderBoxSize. (As long as you don’t invalidate it by writing to those properties before reading them.)

const resizeObserver = new ResizeObserver((entries) => {
let width = entry.borderBoxSize[0].inlineSize; // safe and fast to read
width = entry.target.offsetWidth; // also safe and fast to read!
});
resizeObserver.observe(document.querySelector("div"));

This is a useful alternative to other ways to avoid forced synchronous layout, such as using requestAnimationFrame.