Layout thrashing (även kallat tvingad synkron layout eller forced reflow) uppstår när JavaScript upprepade gånger växlar mellan att skriva till DOM och läsa layoutegenskaper, vilket tvingar webbläsaren att räkna om sidlayouten synkront.
Utlösare för layoutinvalidering
Följande DOM-egenskaper och metoder tvingar fram en synkron omräkning av beräknad geometri när layouten har invaliderats av tidigare DOM-ändringar.
Elementegenskaper & metoder
Boxgeometri & dimensioner
clientHeight,clientWidthclientLeft,clientTopoffsetHeight,offsetWidthoffsetLeft,offsetTopoffsetParentscrollHeight,scrollWidthscrollLeft,scrollTop
Hämta begränsningsrutor
getBoundingClientRect()getClientRects()
Rullningsåtgärder
scrollIntoView()scrollIntoViewIfNeeded()scrollByLines()scrollByPages()
Text & fokus
innerTextouterTextfocus()(tvingar fram fokusring och rullningsjusteringar)
Egenskaper för mushändelser
Att läsa specifika koordinater på ett MouseEvent-objekt kan utlösa layoutberäkning i vissa webbläsarmotorer:
layerX,layerYoffsetX,offsetY
Window-metoder & egenskaper
window.getComputedStyle()(vid förfrågan om layoutberoende värden som bredd, höjd, marginal eller transform)window.scrollBy()window.scrollTo()window.scrollX,window.scrollY
Frame, dokument & bild
- Läsa
widthellerheightpå en bild innan layouten stabiliserats - Åtkomst till
document.body.scrollHeight
jQuery-operationer
Många jQuery-hjälpmetoder läser beräknade layoutvärden under ytan:
// Utlöser reflow
$(elem).offset();
$(elem).offsetParent();
$(elem).position();
$(elem).scrollLeft();
$(elem).scrollTop();
$(elem).css('width'); // Valfri layoutberoende stilberäkning
$(elem).text();
// Pseudoselektorer som kontrollerar geometrisk synlighet
$(':hidden');
$(':visible');
$(':contains');
Bästa praxis för att förhindra Layout Thrashing
1. Gruppera läsningar och skrivningar
Utför alltid alla DOM-mätningar först och samla sedan alla DOM-ändringar i grupp.
// DÅLIGT: Varvad läsning och skrivning tvingar omräkning varje iteration
elements.forEach((el) => {
const width = el.clientWidth; // LÄSNING (tvingar layout)
el.style.width = width * 2 + 'px'; // SKRIVNING (invaliderar layout)
});
// BRA: Gruppera läsningar först, gruppera sedan skrivningar
const widths = elements.map((el) => el.clientWidth); // GRUPPERAD LÄSNING
elements.forEach((el, index) => {
el.style.width = widths[index] * 2 + 'px'; // GRUPPERAD SKRIVNING
});
2. Använd requestAnimationFrame
Schemalägg stilskrivningar till nästa bildruta så att webbläsaren kan optimera renderingscykeln:
const height = element.clientHeight; // Läs under aktuell fas
window.requestAnimationFrame(() => {
element.style.height = height + 50 + 'px'; // Skriv i nästa bildruta
});
3. Använd CSS Transforms & Opacity
Föredra att animera CSS-egenskaper på kompositörstråden (transform, opacity) i stället för layoutegenskaper (top, left, width, height).