Reflows 'ej Repaints: page jank qatlh
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.