Layout thrashing (ook bekend als geforceerde synchrone lay-out of forced reflow) treedt op wanneer JavaScript herhaaldelijk wisselt tussen schrijven naar de DOM en lezen van lay-outeigenschappen, waardoor de browser gedwongen wordt de lay-out synchroon opnieuw te berekenen.
Triggers voor Lay-outinvalidatie
De volgende DOM-eigenschappen en -methoden dwingen een synchrone herberekening van de geometrie af zodra de lay-out ongeldig is gemaakt door eerdere DOM-wijzigingen.
Elementeigenschappen & Methoden
Boxgeometrie & Afmetingen
clientHeight,clientWidthclientLeft,clientTopoffsetHeight,offsetWidthoffsetLeft,offsetTopoffsetParentscrollHeight,scrollWidthscrollLeft,scrollTop
Bounding Boxes Opvragen
getBoundingClientRect()getClientRects()
Scroll-acties
scrollIntoView()scrollIntoViewIfNeeded()scrollByLines()scrollByPages()
Tekst & Focus
innerTextouterTextfocus()(forceert aanpassingen voor focusring en scrollen)
Muisgebeurteniseigenschappen
Het opvragen van bepaalde coördinaten op een MouseEvent-instantie kan lay-outberekening activeren in sommige browserengines:
layerX,layerYoffsetX,offsetY
Window-methoden & Eigenschappen
window.getComputedStyle()(bij het opvragen van lay-outafhankelijke waarden zoals breedte, hoogte, marge of transform)window.scrollBy()window.scrollTo()window.scrollX,window.scrollY
Frame, Document & Afbeelding
widthofheightop een afbeelding opvragen voordat de lay-out stabiel is- Toegang tot
document.body.scrollHeight
jQuery-operaties
Veel jQuery-hulpmethoden lezen onder water berekende lay-outwaarden uit:
// Activeert reflow
$(elem).offset();
$(elem).offsetParent();
$(elem).position();
$(elem).scrollLeft();
$(elem).scrollTop();
$(elem).css('width'); // Elke lay-outafhankelijke stijlberekening
$(elem).text();
// Pseudoselectoren die geometrische zichtbaarheid inspecteren
$(':hidden');
$(':visible');
$(':contains');
Aanbevolen Praktijken tegen Layout Thrashing
1. Lees- en Schrijfopdrachten Bundelen
Voer altijd eerst alle DOM-metingen uit en voer vervolgens alle DOM-mutaties gezamenlijk uit.
// FOUT: Afwisselend lezen en schrijven veroorzaakt bij elke stap een gedwongen lay-out
elements.forEach((el) => {
const width = el.clientWidth; // LEZEN (forceert lay-out)
el.style.width = width * 2 + 'px'; // SCHRIJVEN (invalideert lay-out)
});
// GOED: Eerst gebundeld lezen, daarna gebundeld schrijven
const widths = elements.map((el) => el.clientWidth); // GEBUNDELD LEZEN
elements.forEach((el, index) => {
el.style.width = widths[index] * 2 + 'px'; // GEBUNDELD SCHRIJVEN
});
2. Gebruik requestAnimationFrame
Plan stijlaanpassingen in het volgende animatieframe zodat de browser de rendercyclus kan optimaliseren:
const height = element.clientHeight; // Lezen tijdens huidige fase
window.requestAnimationFrame(() => {
element.style.height = height + 50 + 'px'; // Schrijven in het volgende frame
});
3. Gebruik CSS Transforms & Opacity
Geef voor animaties de voorkeur aan CSS-eigenschappen op de compositor-thread (transform, opacity) in plaats van lay-outeigenschappen (top, left, width, height).