Debounce ResizeObserver Layout Work
Throttle layout work triggered by ResizeObserver so rapid resizes do not thrash the main thread.
Task
Wrap expensive resize handling so it runs at most once per animation frame.
When to use this
A chart recalculates on every resize event, freezing the page while the window is dragged.
Prerequisites
- A component using ResizeObserver
- Expensive layout computation
- A browser to profile
Steps
1. Schedule recalculation on the next animation frame.
let scheduled = false;
const observer = new ResizeObserver(() => {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(() => {
scheduled = false;
recomputeLayout();
});
});
observer.observe(container);Expected output: Layout work runs at most once per frame regardless of observer frequency.
2. Verify only one recalculation per frame.
performance.mark('layout');
// count marks during a resize drag and confirm they match frame countExpected output: Mark count matches frames, not raw resize events.
Troubleshooting
Problem
ResizeObserver loop warnings
Solution
Do not mutate the observed element size synchronously inside the callback.
Problem
Missing final resize
Solution
Trailing debounce ensures the last size is applied.
Limitations
- Animation-frame scheduling still runs during scrolling.
- Does not reduce the cost of a single computation.
- Observer loops must be avoided.
What this recipe does
Wrap expensive resize handling so it runs at most once per animation frame.
A chart recalculates on every resize event, freezing the page while the window is dragged.
Prerequisites
- A component using ResizeObserver
- Expensive layout computation
- A browser to profile
Procedure
- Schedule recalculation on the next animation frame.
let scheduled = false;
const observer = new ResizeObserver(() => {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(() => {
scheduled = false;
recomputeLayout();
});
});
observer.observe(container);
Expected result: Layout work runs at most once per frame regardless of observer frequency.
- Verify only one recalculation per frame.
performance.mark('layout');
// count marks during a resize drag and confirm they match frame count
Expected result: Mark count matches frames, not raw resize events.
How to confirm it worked
Run the commands above and confirm every expected result in order. If a step does not produce the stated output, use the troubleshooting notes before continuing. A passing run shows profiling shows recalculation tied to frame rate, not to raw resize events, and the final size is correct.
Troubleshooting
ResizeObserver loop warnings — Do not mutate the observed element size synchronously inside the callback.
Missing final resize — Trailing debounce ensures the last size is applied.
Limitations
- Animation-frame scheduling still runs during scrolling.
- Does not reduce the cost of a single computation.
- Observer loops must be avoided.