Blog Hoch
Aug 2026·2 tup leghDe'wI' chenmoHta'

Reflows 'ej Repaints: page jank qatlh

#performance#browser#frontend

element height offsetHeight mI', another element width set, width laD, third element height set - 15-line function frame rate Qaw'. culprit "slow JavaScript" legh pagh. browser silently page layout recalculate (multiple times), order request vaD.

reflow nuq

reflow (layout) browser page geometry recompute: element nuqDaq, tIn, text wrap. positions sizes choH: class toggle width choH, new element DOM chel, font download Qu'. repaint Dun: geometry rap, pixels redraw (color shadow choH). reflows Huch: layout change cascade (box resize, bIngDaq Hoch shift).

browsers Sov, default layout work batch. five style properties choH vaj layout five times recompute pagh - next frame wait, wa' pass.

Qagh: layout properties laD

batching Qaw' write qaSDI' layout-dependent property laD. offsetHeight, offsetWidth, getBoundingClientRect(), scrollHeight browser layout up to date vaj answer. laD force immediate synchronous recalculation - batching optimization Qaw'.

const box = document.querySelector('.box');

box.style.width = '300px';       // write
const height = box.offsetHeight; // read — forces a synchronous reflow right here
box.style.height = height + 'px'; // write

wa' write-then-read pair catastrophic pagh. loop Daq vaj damage:

const items = document.querySelectorAll('.item');

items.forEach((item) => {
  item.style.width = '100px';         // write
  const height = item.offsetHeight;   // read — forces reflow, every iteration
  item.style.height = `${height * 2}px`;
});

"layout thrashing": write, read, write, read - read Hoch browser layout work redo (item Hoch). 100 items = 100 forced synchronous reflows (wa' vaD).

fix: reads batch, writes batch

pattern legh vaj fix mechanical: reads Hoch writes Hoch pIm.

const items = document.querySelectorAll('.item');

// Read phase — collect everything first
const heights = Array.from(items).map((item) => item.offsetHeight);

// Write phase — apply everything after
items.forEach((item, i) => {
  item.style.width = '100px';
  item.style.height = `${heights[i] * 2}px`;
});

DaH wa' batch reads (browser layout ghaj, answer) 'ej wa' batch writes (defer, wa' reflow next paint qaSpa').

requestAnimationFrame writes schedule

scroll pagh resize handlers layout changes: write requestAnimationFrame Daq wrap - browser paint cycle qaSpa' land (compete pagh).

let ticking = false;

window.addEventListener('scroll', () => {
  if (ticking) return;
  ticking = true;

  requestAnimationFrame(() => {
    const scrollY = window.scrollY; // read
    header.style.transform = `translateY(${Math.min(scrollY, 100)}px)`; // write
    ticking = false;
  });
});

ticking flag wa' pending frame neH queue. pagh vaj fast scroll callbacks law' queue.

layout skip properties

CSS properties layout paint trigger pagh animate laH - compositor Daq. transform 'ej opacity cha' qatlh:

/* Triggers layout on every frame — avoid animating this */
.slide-in {
  transition: left 0.3s ease;
}

/* Compositor-only — cheap regardless of how large the element is */
.slide-in {
  transition: transform 0.3s ease;
}
// Instead of animating `left`, `top`, `width`, or `height`...
el.style.left = '200px';

// ...animate transform, which doesn't touch layout at all
el.style.transform = 'translateX(200px)';

moving fading element vaD drop-in swap, janky animation highest-leverage change.

thrashing tu'

DevTools Performance panel: reflows purple "Layout" bars. Chrome console "Forced reflow" (stack trace line exact). slow interaction few seconds record, sawtooth pattern purple bars tu'. yellow (script) flat purple pagh vaj thrashing pagh - slow computation (Qagh pIm, fix pIm).

yaj

browser layout work batch Dun - geometry property mid-batch laD vaj early catch up. reads writes pIm, requestAnimationFrame writes defer, transform/opacity (left/width/height pagh) lo'. framework library poQ pagh; operations order neH.

chu'TypeScript Daq state machine machqanHTTP Caching Headers yaj