Feedback

Erzwungener dynamischer Umbruch (Forced Reflow)

Aktualisiert am

Ein erzwungener dynamischer Umbruch, englisch Forced Reflow, entsteht, wenn JavaScript die Seite verändert und gleich danach einen Wert liest, der vom Layout abhängt, etwa offsetWidth, getBoundingClientRect() oder scrollTop. Der Browser kann diesen Wert nicht aus dem alten Layout beantworten. Er hält das Skript an, berechnet Stile und Layout sofort neu und gibt erst dann das Ergebnis zurück. Einmal ausgeführt, kostet das wenig. In einer Schleife oder in einem Scroll-Handler wird daraus sogenanntes Layout-Thrashing, das den Hauptthread für Dutzende oder Hunderte Millisekunden blockiert. Lighthouse 13 meldet das als Insight „Erzwungener dynamischer Umbruch“, die Chrome-Konsole kennt die verwandte Warnung „[Violation] Forced reflow while executing JavaScript took … ms“.

Aus den Messungen von PerfDelta: Im mobilen Labortest erreichen 24 % von 5.642 Startseiten bei Total Blocking Time einen guten Wert, 54 % liegen im schlechten Bereich. Der Median liegt bei 671 ms, die mittlere Hälfte zwischen 210 ms und 1505 ms. Mehr dazu im Datenblock unten.

Das Insight in Lighthouse 13 und PageSpeed Insights

Das Insight ist mit Lighthouse 13 neu hinzugekommen und hat keine Vorgängerprüfung (Lighthouse-Quellcode, core/audits/insights/forced-reflow-insight.js, Version 13.5, abgerufen am 18.10.2026). Die deutsche Bezeichnung stammt aus der offiziellen Übersetzung, in englischen Berichten heißt es „Forced reflow“. Es zeigt zwei Tabellen:

Im Pagespeed-Score hat das Insight kein Gewicht. Die gemessene Zeit gehört aber zur Arbeit des Hauptthreads und erscheint im Labor als Total Blocking Time. Fällt sie bei Klicks, Taps oder Eingaben an, verschlechtert sie im Feld den Interaction to Next Paint. Die Chrome-Dokumentation nennt als Ziel, dass kein erzwungener Umbruch länger als 30 Millisekunden dauert (Chrome for Developers, Forced reflow).

Wodurch ein erzwungener Umbruch entsteht

Normalerweise bündelt der Browser die Arbeit: Skripte ändern DOM und Stile, Stilberechnung und Layout laufen einmal vor dem nächsten Frame. Ein erzwungener Umbruch durchbricht diese Bündelung. Das Muster besteht immer aus zwei Schritten in derselben Aufgabe, einem Schreibzugriff, der das Layout ungültig macht, und einem Lesezugriff, der das aktuelle Layout braucht.

Schreibzugriffe sind etwa das Ändern von Klassen oder Inline-Stilen, das Einfügen oder Entfernen von Elementen, geänderter Text und das Setzen von width, height, top oder left. Lesezugriffe, die ein Layout erzwingen können, sind unter anderem offsetWidth, offsetHeight, clientWidth, scrollHeight, scrollTop, getBoundingClientRect(), getComputedStyle(), innerText, focus() und scrollIntoView().

In der Praxis stecken dahinter oft Skripte für gleich hohe Karten, Kopfzeilen, die bei jedem Scroll-Ereignis ihre Position messen, Slider, die jede Folie nach dem Einfügen ausmessen, Masonry-Raster, Skripte zum Kürzen von Text und Widgets von Drittanbietern, die ihre iFrames anpassen. Ein großes DOM macht jeden Umbruch teurer, weil mehr Elemente neu berechnet werden; diese Seite behandelt der Ratgeber DOM-Größe reduzieren.

Den Code in den Chrome DevTools finden

  1. Öffnen Sie das Performance-Panel, aktivieren Sie die CPU-Drosselung (vier- oder sechsfach) und zeichnen Sie das Laden der Seite oder die langsame Interaktion auf.
  2. Öffnen Sie in der Insights-Seitenleiste „Erzwungener dynamischer Umbruch“. Ein Klick auf einen Eintrag markiert die zugehörigen Aufgaben in der Hauptspur.
  3. Erzwungene Layouts erscheinen in der Hauptspur als violette Layout-Ereignisse mit rotem Dreieck. Die Zusammenfassung eines solchen Ereignisses zeigt eine Warnung und verlinkt die auslösende Funktion samt Zeile.
  4. Laden Sie die Source Maps Ihres Bundles, damit die Codestellen auf Ihre eigenen Dateien zeigen und nicht auf minimierten Code.

Bei echten Nutzern meldet die Long Animation Frames API dieselben Kosten je Skript als forcedStyleAndLayoutDuration. Damit sehen Sie, ob Besucher bei Interaktionen tatsächlich darauf treffen:

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    for (const script of entry.scripts) {
      if (script.forcedStyleAndLayoutDuration > 30) {
        console.log(script.sourceURL, script.sourceFunctionName, Math.round(script.forcedStyleAndLayoutDuration) + ' ms');
      }
    }
  }
}).observe({ type: 'long-animation-frame', buffered: true });

Erzwungene Umbrüche beheben

Erst lesen, dann schreiben

Die häufigste Ursache ist eine Schleife, die Schreib- und Lesezugriffe abwechselt. Jede Runde macht das Layout ungültig, der nächste Lesezugriff erzwingt es erneut. Trennen Sie beides, dann rechnet der Browser nur einmal:

// Langsam: jede Karte erzwingt ein eigenes Layout
cards.forEach((card) => {
  card.style.height = '';                        // Schreiben
  card.style.height = card.offsetHeight + 'px';  // Lesen erzwingt Layout
});

// Schnell: alle Schreibzugriffe, ein Lesedurchgang, dann wieder schreiben
cards.forEach((card) => { card.style.height = ''; });
const max = Math.max(...cards.map((card) => card.offsetHeight));
cards.forEach((card) => { card.style.height = max + 'px'; });

Messungen in den nächsten Frame verschieben

Muss der Code nach einer Änderung messen, verlegen Sie den Lesezugriff an eine Stelle, an der der Browser ohnehin ein Layout berechnet hat. Ein verschachtelter Aufruf von requestAnimationFrame liest nach dem Layout des folgenden Frames:

element.classList.add('is-open');
requestAnimationFrame(() => {
  requestAnimationFrame(() => {
    const height = element.getBoundingClientRect().height;
    updateIndicator(height);
  });
});

Observer messen lassen

Statt bei jedem Scroll- oder Resize-Ereignis zu messen, lassen Sie den Browser Änderungen melden: ResizeObserver für Größenänderungen, IntersectionObserver für Sichtbarkeit und klebende Kopfzeilen. Beide liefern ihre Ergebnisse nach dem Layout, ohne es zu erzwingen.

const header = document.querySelector('.site-header');
new IntersectionObserver(([entry]) => {
  header.classList.toggle('is-stuck', entry.intersectionRatio < 1);
}, { threshold: [1] }).observe(document.querySelector('.header-sentinel'));

Layout per CSS statt per Skript

Viele messende Skripte stammen aus einer Zeit, in der CSS die Aufgabe nicht lösen konnte. Gleich hohe Karten gelingen mit Flexbox oder Grid, klebende Elemente mit position: sticky, gekürzter Text mit line-clamp, feste Seitenverhältnisse mit aspect-ratio. Entfällt das Skript, entfällt auch der Umbruch.

transform und opacity animieren

Animationen über top, left, width oder height lösen in jedem Frame ein Layout aus, sobald der Code zusätzlich Positionen liest. transform und opacity kommen ohne Layout aus; CSS-Übergänge und die Web Animations API halten die Arbeit nach Möglichkeit vom Hauptthread fern.

Den Umfang jedes Layouts begrenzen

contain: layout oder contain: content an abgeschlossenen Komponenten und content-visibility: auto an langen Abschnitten unterhalb des sichtbaren Bereichs verkleinern den Teil der Seite, den ein Umbruch neu berechnen muss.

Drittanbieter und Frameworks

Zeigen die Codestellen auf ein Chat-Widget, ein Consent-Tool oder ein Werbeskript, liegt die Lösung außerhalb Ihres Codes. Aktualisieren Sie das Skript, laden Sie es erst nach der ersten Interaktion oder ersetzen Sie es; die Möglichkeiten beschreibt der Ratgeber Drittanbieter-Code. In Frameworks entstehen erzwungene Umbrüche häufig in useLayoutEffect oder vergleichbaren Hooks, die nach jedem Rendern messen. Verlagern Sie solche Messungen in Observer oder führen Sie sie nur aus, wenn sich die Eingabe wirklich geändert hat.

Ergebnis prüfen

Zeichnen Sie dasselbe Laden oder dieselbe Interaktion mit gleicher Drosselung erneut auf. Die Gesamtzeit im Insight sollte sinken, die markierten Layout-Ereignisse sollten aus den betroffenen Aufgaben verschwinden und die Total Blocking Time im Labor fallen. Ob der INP echter Nutzer besser wird, zeigen die Felddaten nach einigen Wochen. Der kostenlose Website Speed Test von PerfDelta stellt TBT und INP aus den Felddaten für mehrere Seiten nebeneinander. So sehen Sie vor dem Griff zu den DevTools, welche Vorlagen betroffen sind.

Häufige Fragen

Was bedeutet „[Violation] Forced reflow while executing JavaScript took 50ms“?

Chrome schreibt diese Warnung in die Konsole, wenn ein Skript ein Layout erzwungen hat, das länger als erwartet dauerte. Sie weist auf dasselbe Problem hin wie das Lighthouse-Insight. Welche Funktion es ausgelöst hat, zeigt das Performance-Panel.

Ist ein erzwungener Umbruch immer schlecht?

Nein. Eine einzelne Messung nach einer Änderung kostet auf einer kleinen Seite wenig. Zum Problem wird sie in Schleifen, Scroll-Handlern und Animationen oder bei großem DOM. Die Chrome-Dokumentation setzt deshalb 30 Millisekunden als Grenze.

Beeinflusst das Insight den Lighthouse-Score?

Nicht direkt. Die gemessene Zeit gehört zur Arbeit des Hauptthreads und damit zur Total Blocking Time, die 30 Prozent des Scores ausmacht.

Was ist der Unterschied zwischen Reflow und Repaint?

Beim Reflow, also dem Layout, berechnet der Browser Größe und Position der Elemente. Beim Repaint zeichnet er Pixel neu, ohne die Geometrie zu ändern, etwa nach einem Farbwechsel. Der Reflow ist teurer, und nur er lässt sich durch das Lesen von Layout-Werten erzwingen.

Was die Messdaten von PerfDelta zeigen

Im mobilen Labortest erreichen 24 % von 5.642 Startseiten bei Total Blocking Time einen guten Wert, 54 % liegen im schlechten Bereich. Der Median liegt bei 671 ms, die mittlere Hälfte zwischen 210 ms und 1505 ms.

Erzwungene Umbrüche erfasst PerfDelta nicht als eigene Kennzahl; sie verlängern die Tasks im Hauptthread und damit die Total Blocking Time im Labor und den INP im Feld.

Nach Branche reicht der Median von 257 ms im Bereich Beratung und Dienstleistung bis 1155 ms im Bereich Reise und Hotellerie.

Datenstand 18.10.2026, täglich neu berechnet. Quelle: eigene Messungen von PerfDelta (Chrome UX Report und Lighthouse), Details in den Website Speed Statistiken und in der Methodik.

Grenzwerte und Quellen

Quellen:

Alle Quellen abgerufen am 18.10.2026. Grenzwerte und Dokumentation ändern sich; maßgeblich ist die verlinkte Seite.

Eigene Werte testen

Ein kostenloser Scan zeigt, wie Ihre Seiten bei diesen Werten abschneiden, mobil und stationär, mit Feld- und Labdaten nebeneinander.

Kostenlosen Test starten

Mit einem kostenlosen Konto speichern Sie Ihre Messungen und sehen, wie sich die Werte von Test zu Test verändern. Tägliches Monitoring mit Felddaten und Benachrichtigung gibt es ab dem Tarif Solo.

Verwandte Themen