Fehler bei Layout Shifts beheben

Informationen zum Identifizieren und Beheben von Layoutverschiebungen

Katie Hempenius
Katie Hempenius

Im ersten Teil dieses Artikels werden Tools zum Beheben von Layoutänderungen beschrieben. Im zweiten Teil wird erläutert, wie Sie die Ursache für eine Layoutänderung ermitteln.

Tools

Layout Instability API

Die Layout Instability API ist der Browsermechanismus zum Messen und Melden von Layoutänderungen. Alle Tools zum Debuggen von Layoutverschiebungen, einschließlich DevTools, basieren letztendlich auf der Layout Instability API. Die direkte Verwendung der Layout Instability API ist jedoch aufgrund ihrer Flexibilität ein leistungsstarkes Tool zur Fehlerbehebung.

Nutzung

Mit demselben Code-Snippet, mit dem der Cumulative Layout Shift (CLS) gemessen wird, können Sie auch Layoutverschiebungen beheben. Im folgenden Snippet werden Informationen zu Layoutänderungen in der Konsole protokolliert. In diesem Protokoll finden Sie Informationen dazu, wann, wo und wie eine Layoutänderung aufgetreten ist.

let cls = 0;
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

Beachten Sie beim Ausführen dieses Scripts Folgendes:

  • Die Option buffered: true gibt an, dass PerformanceObserver den Leistungseintragsbuffer des Browsers auf Leistungseinträge prüfen soll, die vor der Initialisierung des Beobachters erstellt wurden. Daher werden mit PerformanceObserver Layoutänderungen erfasst, die sowohl vor als auch nach der Initialisierung aufgetreten sind. Beachten Sie dies, wenn Sie die Konsolenprotokolle prüfen. Ein anfänglicher Überfluss an Layoutänderungen kann auf einen Berichtsrückstand zurückzuführen sein und nicht auf das plötzliche Auftreten zahlreicher Layoutänderungen.
  • Um Leistungseinbußen zu vermeiden, wartet PerformanceObserver, bis der Haupt-Thread inaktiv ist, bevor er Layoutänderungen meldet. Je nachdem, wie ausgelastet der Hauptthread ist, kann es daher zu einer leichten Verzögerung zwischen dem Auftreten einer Layoutänderung und der Protokollierung in der Konsole kommen.
  • Dieses Script ignoriert Layoutverschiebungen, die innerhalb von 500 Millisekunden nach einer Nutzereingabe aufgetreten sind und daher nicht auf die CLS angerechnet werden.

Informationen zu Layoutänderungen werden mithilfe einer Kombination aus zwei APIs erfasst: den Schnittstellen LayoutShift und LayoutShiftAttribution. Jede dieser Schnittstellen wird in den folgenden Abschnitten ausführlicher erläutert.

LayoutShift

Jede Layoutänderung wird über die LayoutShift-Schnittstelle erfasst. Der Inhalt eines Eintrags sieht so aus:

duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798

Der Eintrag oben weist auf eine Layoutänderung hin, bei der sich die Position von drei DOM-Elementen geändert hat. Das Layout-Shift-Ergebnis dieses bestimmten Layout-Shifts war 0.175.

Dies sind die Eigenschaften einer LayoutShift-Instanz, die für das Debuggen von Layoutänderungen am relevantesten sind:

Attribut Beschreibung
sources In der Property sources werden die DOM-Elemente aufgeführt, die während der Layoutänderung verschoben wurden. Dieses Array kann bis zu fünf Quellen enthalten. Falls mehr als fünf Elemente vom Layout-Shift betroffen sind, werden die fünf größten Quellen des Layout-Shifts (gemessen an der Auswirkung auf die Layoutstabilität) gemeldet. Diese Informationen werden über die Schnittstelle „LayoutShiftAttribution“ erfasst (siehe unten).
value Die Property value gibt den Wert für Layoutänderungen für eine bestimmte Layoutänderung an.
hadRecentInput Die hadRecentInput-Eigenschaft gibt an, ob innerhalb von 500 Millisekunden nach einer Nutzereingabe ein Layout-Shift aufgetreten ist.
startTime Mit dem Attribut startTime wird angegeben, wann eine Layoutänderung stattgefunden hat. startTime wird in Millisekunden angegeben und bezogen auf den Zeitpunkt, zu dem der Seitenaufbau gestartet wurde gemessen.
duration Die Property duration ist immer auf 0 festgelegt. Diese Property wird von der PerformanceEntry-Oberfläche übernommen (die LayoutShift-Oberfläche erweitert die PerformanceEntry-Oberfläche). Das Konzept der Dauer gilt jedoch nicht für Layout-Änderungsereignisse. Daher wird hier 0 festgelegt. Weitere Informationen zur PerformanceEntry-Oberfläche finden Sie in der Spezifikation.

LayoutShiftAttribution

Die LayoutShiftAttribution-Schnittstelle beschreibt eine einzelne Verschiebung eines einzelnen DOM-Elements. Wenn sich bei einer Layoutänderung mehrere Elemente verschieben, enthält die Property sources mehrere Einträge.

Das folgende JSON entspricht beispielsweise einer Layoutverschiebung mit einer Quelle: die Verschiebung des DOM-Elements <div id='banner'> von y: 76 nach y:246 nach unten.

// ...
  "sources": [
    {
      "node": "div#banner",
      "previousRect": {
        "x": 311,
        "y": 76,
        "width": 4,
        "height": 18,
        "top": 76,
        "right": 315,
        "bottom": 94,
        "left": 311
      },
      "currentRect": {
        "x": 311,
        "y": 246,
        "width": 4,
        "height": 18,
        "top": 246,
        "right": 315,
        "bottom": 264,
        "left": 311
      }
    }
  ]

Mit der Property node wird das verschobene HTML-Element angegeben. Wenn Sie den Mauszeiger in den DevTools auf diese Eigenschaft bewegen, wird das entsprechende Seitenelement hervorgehoben.

Die Eigenschaften previousRect und currentRect geben die Größe und Position des Knotens an.

  • Die Koordinaten x und y geben die X- und Y-Koordinate der linken oberen Ecke des Elements an.
  • Die Eigenschaften width und height geben die Breite und Höhe des Elements an.
  • Die Eigenschaften top, right, bottom und left geben die X- oder Y-Koordinatenwerte für die angegebene Kante des Elements an. Mit anderen Worten: Der Wert von top ist gleich y und der Wert von bottom ist gleich y+height.

Wenn alle Eigenschaften von previousRect auf 0 gesetzt sind, ist das Element sichtbar. Wenn alle Properties von currentRect auf 0 gesetzt sind, ist das Element nicht sichtbar.

Bei der Interpretation dieser Ausgabe ist es wichtig zu wissen, dass Elemente, die als Quellen aufgeführt sind, die Elemente sind, die sich während der Layoutänderung verschoben haben. Es ist jedoch möglich, dass diese Elemente nur indirekt mit der „Ursache“ der Layoutinstabilität zusammenhängen. Hier einige Beispiele:

Beispiel 1

Diese Layoutänderung wird mit einer Quelle erfasst: Element B. Die eigentliche Ursache für diese Layoutänderung ist jedoch die Änderung der Größe von Element A.

Beispiel für eine Layoutänderung, die durch eine Änderung der Elementabmessungen verursacht wird

Beispiel 2

Die Layoutänderung in diesem Beispiel wird mit zwei Quellen erfasst: Element A und Element B. Die Ursache für diese Layoutverschiebung ist die Änderung der Position von Element A.

Beispiel für eine Layoutänderung, die durch eine Änderung der Elementposition verursacht wird

Beispiel 3

Die Layoutänderung in diesem Beispiel wird mit einer Quelle erfasst: Element B. Die Änderung der Position von Element B hat zu dieser Layoutänderung geführt.

Beispiel für eine Layoutänderung, die durch eine Änderung der Elementposition verursacht wird

Beispiel 4

Obwohl sich Element B ändert, gibt es in diesem Beispiel keine Layoutänderung.

Beispiel für ein Element, das sich ändert, aber keine Layoutänderung verursacht

Demo, wie DOM-Änderungen von der Layout Instability API gemeldet werden

Entwicklertools

Bereich „Leistung“

Im Bereich Nutzerfreundlichkeit des Bereichs Leistung in den DevTools werden alle Layoutverschiebungen angezeigt, die während eines bestimmten Leistungs-Traces auftreten – auch wenn sie innerhalb von 500 Millisekunden nach einer Nutzerinteraktion erfolgen und daher nicht auf die CLS angerechnet werden. Wenn Sie im Bereich Website den Mauszeiger auf einen bestimmten Layout-Shift bewegen, wird das betroffene DOM-Element hervorgehoben.

Screenshot einer Layoutänderung, die im Bereich „Netzwerk“ der Entwicklertools angezeigt wird

Wenn Sie weitere Informationen zur Layoutänderung sehen möchten, klicken Sie auf die Layoutänderung und öffnen Sie den Bereich Zusammenfassung. Änderungen an den Abmessungen des Elements werden im Format [width, height] aufgeführt, Änderungen an der Position des Elements im Format [x,y]. Mit der Property Vor Kurzem Eingaben wird angegeben, ob innerhalb von 500 Millisekunden nach einer Nutzerinteraktion eine Layoutänderung stattgefunden hat.

Screenshot des Tabs „Zusammenfassung“ in den DevTools für einen Layout-Shift

Informationen zur Dauer einer Layoutänderung finden Sie auf dem Tab Ereignisprotokoll. Die Dauer einer Layoutänderung lässt sich auch anhand der Länge des roten Rechtecks für die Layoutänderung im Bereich Website schätzen.

Screenshot des Tabs „Ereignisprotokoll“ in den DevTools für einen Layout-Shift

Weitere Informationen zur Verwendung des Bereichs Leistung finden Sie in der Referenz zur Leistungsanalyse.

Layout Shift-Bereiche hervorheben

Wenn Sie Bereiche mit Layout-Shifts hervorheben, können Sie sich schnell einen Überblick über die Position und das Timing der Layout-Shifts auf einer Seite verschaffen.

Wenn Sie Layout-Verschiebungsregionen in den Entwicklertools aktivieren möchten, gehen Sie zu Einstellungen > Weitere Tools > Rendering > Layout-Verschiebungsregionen und aktualisieren Sie die Seite, die Sie debuggen möchten. Bereiche mit Layout-Shift werden kurzzeitig lila hervorgehoben.

Vorgehensweise zur Identifizierung der Ursache von Layoutänderungen

Mit den folgenden Schritten können Sie die Ursache für Layoutverschiebungen ermitteln, unabhängig davon, wann oder wie sie auftreten. Diese Schritte können durch das Ausführen von Lighthouse ergänzt werden. Beachten Sie jedoch, dass Lighthouse nur Layoutverschiebungen erkennen kann, die beim ersten Laden der Seite aufgetreten sind. Außerdem kann Lighthouse nur Vorschläge für einige Ursachen von Layoutänderungen machen, z. B. für Bildelemente, die keine explizite Breite und Höhe haben.

Ursache für einen Layout-Shift ermitteln

Layoutänderungen können durch die folgenden Ereignisse verursacht werden:

  • Änderungen an der Position eines DOM-Elements
  • Änderungen an den Abmessungen eines DOM-Elements
  • Einfügen oder Entfernen eines DOM-Elements
  • Layout auslösende Animationen

Insbesondere ist das DOM-Element, das direkt vor dem verschobenen Element steht, am wahrscheinlichsten für die Layoutverschiebung verantwortlich. Wenn Sie also untersuchen, warum ein Layout-Shift aufgetreten ist, sollten Sie Folgendes berücksichtigen:

  • Haben sich die Position oder die Abmessungen des vorherigen Elements geändert?
  • Wurde vor dem verschobenen Element ein DOM-Element eingefügt oder entfernt?
  • Wurde die Position des verschobenen Elements explizit geändert?

Wenn das vorausgehende Element nicht für die Layoutverschiebung verantwortlich ist, fahren Sie mit der Suche fort und prüfen Sie andere vorausgehende und nahe gelegene Elemente.

Außerdem können die Richtung und der Abstand einer Layoutverschiebung Hinweise auf die Ursache geben. Eine große Verschiebung nach unten weist beispielsweise oft auf das Einfügen eines DOM-Elements hin, während eine Layoutverschiebung von 1 px oder 2 px oft auf die Anwendung in Konflikt stehender CSS-Stile oder das Laden und Anwenden einer Webschriftart hinweist.

Diagramm mit einer Layoutänderung, die durch einen Schriftschnittwechsel verursacht wurde
In diesem Beispiel haben sich die Seitenelemente durch den Schriftartwechsel um fünf Pixel nach oben verschoben.

Im Folgenden finden Sie einige der spezifischen Verhaltensweisen, die am häufigsten zu Layout-Shift-Ereignissen führen:

Änderungen an der Position eines Elements, die nicht auf die Bewegung eines anderen Elements zurückzuführen sind

Diese Art von Änderung ist oft auf Folgendes zurückzuführen:

  • Stylesheets, die spät geladen werden oder zuvor deklarierte Stile überschreiben.
  • Animationen und Übergänge

Änderungen an den Abmessungen eines Elements

Diese Art von Änderung ist oft auf Folgendes zurückzuführen:

  • Stylesheets, die spät geladen werden oder zuvor deklarierte Stile überschreiben.
  • Bilder und Iframes ohne width- und height-Attribute, die geladen werden, nachdem ihr „Slot“ gerendert wurde.
  • Textblöcke ohne width- oder height-Attribute, bei denen die Schriftart nach dem Rendern des Texts geändert wird

Einfügen oder Entfernen von DOM-Elementen

Das kann folgende Gründe haben:

  • Einfügen von Anzeigen und anderen Einbettungen von Drittanbietern
  • Einfügen von Bannern, Benachrichtigungen und Modalfenstern
  • Unendliches Scrollen und andere UX-Muster, bei denen zusätzliche Inhalte über vorhandenen Inhalten geladen werden

Layout auslösende Animationen

Einige Animationen können Layoutänderungen auslösen. Ein häufiges Beispiel hierfür ist, wenn DOM-Elemente durch Inkrementieren von Eigenschaften wie top oder left animiert werden, anstatt die CSS-Eigenschaft transform zu verwenden. Weitere Informationen finden Sie unter Hochleistungs-CSS-Animationen erstellen.

Layout-Shifts reproduzieren

Layoutverschiebungen, die nicht reproduzierbar sind, können nicht behoben werden. Eine der einfachsten und gleichzeitig effektivsten Methoden, um die Layoutstabilität Ihrer Website besser zu beurteilen, besteht darin, 5 bis 10 Minuten lang mit Ihrer Website zu interagieren, um Layoutänderungen auszulösen. Lassen Sie die Console dabei geöffnet und verwenden Sie die Layout Instability API, um Layoutänderungen zu melden.

Wenn Sie Layoutänderungen nur schwer finden, wiederholen Sie diese Übung mit verschiedenen Geräten und Verbindungsgeschwindigkeiten. Insbesondere kann es einfacher sein, Layoutänderungen zu erkennen, wenn Sie eine langsamere Verbindungsgeschwindigkeit verwenden. Außerdem können Sie eine debugger-Anweisung verwenden, um Layoutänderungen einfacher zu durchgehen.

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      debugger;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

Bei Layoutproblemen, die in der Entwicklung nicht reproduzierbar sind, können Sie die Layout Instability API in Verbindung mit Ihrem bevorzugten Front-End-Logging-Tool verwenden, um weitere Informationen zu diesen Problemen zu erhalten. In diesem Beispielcode wird gezeigt, wie Sie das größte verschobene Element auf einer Seite erfassen.