sfw/fix
[Violation] Forced reflow medium

Chrome console "[Violation] Forced reflow while executing JavaScript took NNms"

JavaScript read a layout property right after writing to the DOM, forcing the browser to recalculate layout synchronously mid-script.

What you see

[Violation] Forced reflow while executing JavaScript took 53ms

What’s actually happening

A yellow [Violation] warning shows up in the console, usually during scroll, resize, or an animation. The page feels janky — scrolling stutters, interactions lag. The NNms figure is how long the synchronous layout recalculation blocked the main thread; anything over ~30ms is noticeable, and it often repeats every frame.

Common causes

  • A loop that writes a style then immediately reads a layout property (el.style.width = x; const h = el.offsetHeight) — each read forces a fresh layout because the write invalidated the last one
  • Reading getBoundingClientRect, offsetTop, scrollHeight, or clientWidth inside a scroll or resize handler that also mutates the DOM
  • Animating layout-triggering properties (top, left, width, height, margin) via JS instead of transform/opacity
  • A third-party script (ads, analytics, sliders) measuring elements repeatedly without batching
  • Reading offsetWidth on many elements in one pass while interleaving class changes — classic layout thrashing across a list

How to fix it

  1. Find the offender in the Performance panelRecord a trace in DevTools Performance while reproducing the jank. Look for tall purple 'Recalculate Style / Layout' bars with a warning triangle; click one and check 'Summary' for the stack. That points you at the exact line reading layout.
  2. Batch reads, then writesSeparate measurement from mutation. Read all the layout values you need into variables first, then apply all DOM/style changes after. Never read-write-read-write in a loop — that's what forces repeated reflows.
  3. Defer reads with requestAnimationFrameMove layout reads into a requestAnimationFrame callback so they happen at a consistent point in the frame, after style changes have flushed. For read-then-write patterns, libraries like fastdom formalize this split if hand-batching gets unwieldy.
  4. Animate with transform and opacity onlyReplace JS-driven top/left/width animations with CSS transform: translate() and opacity, which the compositor handles off the main thread and don't trigger layout. Add will-change sparingly on the animated element.
  5. Cache layout values outside loopsIf you need a container's width inside a loop over 200 items, read it once before the loop into a const. Re-reading offsetWidth per iteration is the most common accidental thrash.

Stop it recurring

Keep DOM reads and writes in separate phases — measure everything, then mutate everything — and animate only transform/opacity.

Related errors