Hurtigere hjemmeside hjælp til en langsom hjemmeside

Layout thrashing

Layout thrashing opstår når kode skifter mellem DOM-reads og DOM-writes på en måde der tvinger browseren til synkront layout (reflow) gentagne gange. Det skader INP og gør UI hakkende.

Skrevet af Kim Tetzlaff

Kort fortalt: Layout thrashing er når din kode gør browserens rendering dyrere ved at skifte mellem at læse layout og skrive layout på en måde der tvinger browseren til at lave layout (reflow) igen og igen – ofte i samme frame. Resultatet er dårligere INP, hakkende scroll og UI der føles tungt.

Hvad betyder layout thrashing?

Browseren prøver normalt at være smart:

  • Den samler (batch’er) style/layout/paint så den kan gøre det effektivt.

Men hvis du:

  1. ændrer DOM eller styles (write)
  2. måler layout (read)
  3. ændrer igen (write)
  4. måler igen (read)

…så kan du tvinge browseren til at “lukke regnskabet” hver gang: “Okay, jeg er nødt til at beregne layout nu, fordi du spørger efter det.”

Det er forced synchronous layout i praksis.

Hvorfor er det vigtigt?

Layout thrashing rammer især:

  • interaktioner (klik, drag, åbne/lukke panels)
  • animationer og scroll listeners
  • komponenter der opdaterer mange elementer på én gang

Og det ses ofte som:

  • lange frames (UI hakker)
  • flere layout-events i Performance trace
  • højere INP for brugere på mobil/low-end CPU

Eksempel fra praksis

Du har en liste og vil animere højde:

  1. Sæt element.style.height = ... (write)
  2. Læs element.offsetHeight (read)
  3. Sæt en ny klasse (write)
  4. Læs getBoundingClientRect() (read)

Hvis det sker i en loop over mange elementer, eksploderer omkostningen.

Typiske årsager

  • Målinger i loops (for/map) hvor du både ændrer og måler per iteration
  • scroll-handlers der måler DOM og skriver styles mange gange pr. sekund
  • “smart” UI-kode der prøver at beregne positioner dynamisk uden batching
  • Tredjeparts widgets der manipulerer DOM på uheldige tidspunkter (se Third-party scripts)

Sådan finder du det

Brug Chrome DevTools Performance:

  • Optag en interaktion.
  • Kig efter “Recalculate Style” og “Layout” events.
  • Tjek stack traces: ofte peger de direkte på det stykke kode der læser offset*, client*, scroll* eller getBoundingClientRect.

Sådan løser du det (praktiske greb)

1) Batch reads og writes

Et robust mønster er:

  • Først: læs alt det du skal bruge (reads)
  • Derefter: lav alle DOM-ændringer (writes)

Det føles “kedeligt”, men det er ofte den største enkelt-gevinst.

2) Undgå at måle i hver frame

Hvis du kan:

  • cache målinger
  • opdater kun når layout faktisk ændrer sig (resize, content change)

3) Brug CSS hvor det er muligt

Hvis du kan lave effekten i CSS (fx transitions) uden at måle alt i JS, får browseren mulighed for at optimere.

4) Begræns DOM-arbejde

Layout thrashing bliver værre jo større DOM du har. Overvej:

  • færre nodes
  • mindre “re-render” pr. click
  • eller isolér områder (fx med contain, se CSS contain)

Relaterede begreber

  • Event loop – hvorfor layout og JS kæmper om samme main thread
  • INP – metrikken der ofte afslører problemet
  • Long Task – når JS-blokke i sig selv er for lange
  • Main thread – grundforklaringen på “én ting ad gangen”

FAQ

Hvordan ved jeg om jeg har layout thrashing?

Et typisk tegn er at interaktioner føles tunge, og at DevTools Performance viser mange layout-kørsler (Recalculate Style/Layout) tæt på hinanden, ofte udløst af DOM-målinger som `getBoundingClientRect()`.

Er det kun et JavaScript-problem?

Det udløses typisk af JavaScript, men roden er samspillet mellem JS og rendering: når du måler layout efter at have ændret DOM, kan browseren blive tvunget til at gøre layout færdigt synkront.

Eksterne kilder

DevTools og klassiske forklaringer af forced reflow dækker mønstrene og løsningerne.

Næste skridt fra begreb til handling

Guides og blogindlæg der matcher begrebets emne - ud fra fælles tags og sidens fokus.

Om forfatteren

Kim Tetzlaff

Kim skriver og vedligeholder indhold på hurtigere-hjemmeside.dk med fokus på målelig performance, Core Web Vitals og teknisk SEO. Målet er at gøre optimering konkret: hvad der faktisk flytter tal i feltdata, og hvordan du finder den korteste vej fra symptom til fix.

Kim Tetzlaff