So beheben Sie Probleme mit der kumulativen Layoutverschiebung (CLS).

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Die Core Web Vitals-Initiative von Google hat die SEO- und Web-Performance-Welten im Sturm erobert, und viele Websites sind damit beschäftigt, ihre Page Experience zu optimieren, um den Ranking-Faktor zu maximieren. Die Metrik „Cumulative Layout Shift“ bereitet vielen Websites Probleme, also schauen wir uns an, wie wir Probleme mit dieser Metrik beheben können.

Cumulative Layout Shift (CLS) versucht, diese erschütternden Bewegungen der Seite zu messen, wenn neue Inhalte – seien es Bilder, Anzeigen oder was auch immer – später als der Rest der Seite ins Spiel kommen. Es berechnet eine Punktzahl basierend darauf, wie viel auf der Seite sich unerwartet bewegt und wie oft. Diese Inhaltsverschiebungen sind sehr ärgerlich und führen dazu, dass Sie Ihren Platz in einem Artikel verlieren, den Sie zu lesen begonnen haben, oder, noch schlimmer, dazu führen, dass Sie auf die falsche Schaltfläche klicken!

In diesem Artikel werde ich einige Front-End-Muster diskutieren, um CLS zu reduzieren . Ich werde nicht zu viel über die Messung von CLS sprechen, da ich das bereits in einem früheren Artikel behandelt habe. Ich werde auch nicht zu viel über die Mechanismen sprechen, wie CLS berechnet wird: Google hat einige gute Dokumentationen dazu, und Jess Pecks The Almost-Complete Guide to Cumulative Layout Shift ist auch ein toller tiefer Einblick in das. Ich werde jedoch ein wenig Hintergrundwissen geben, das erforderlich ist, um einige der Techniken zu verstehen.

Warum CLS anders ist

CLS ist meiner Meinung nach das interessanteste der Core Web Vitals, zum Teil, weil es etwas ist, für das wir noch nie wirklich gemessen oder optimiert haben. Daher erfordert es oft neue Techniken und Denkweisen, um zu versuchen, es zu optimieren. Es ist ein ganz anderes Biest als die beiden anderen Core Web Vitals.

Bei einem kurzen Blick auf die beiden anderen Core Web Vitals macht Largest Contentful Paint (LCP) genau das, was der Name vermuten lässt, und ist eher eine Wendung früherer Lademetriken, die messen, wie schnell die Seite geladen wird. Ja, wir haben die Definition der Benutzererfahrung beim Laden der Seite geändert, um die Ladegeschwindigkeit der relevantesten Inhalte zu berücksichtigen , aber im Grunde werden die alten Techniken wiederverwendet, um sicherzustellen, dass die Inhalte so schnell wie möglich geladen werden. Wie Sie Ihr LCP optimieren, sollte für die meisten Webseiten ein relativ gut verstandenes Problem sein.

First Input Delay (FID) misst alle Verzögerungen bei Interaktionen und scheint für die meisten Websites kein Problem zu sein. Die Optimierung ist normalerweise eine Frage der Bereinigung (oder Reduzierung!) Ihres JavaScripts und ist normalerweise seitenspezifisch. Das heißt nicht, dass die Lösung von Problemen mit diesen beiden Metriken einfach ist, aber es handelt sich um einigermaßen gut verstandene Probleme.

Ein Grund dafür, dass CLS anders ist, ist, dass es über die Lebensdauer der Seite gemessen wird – das ist der „kumulative“ Teil des Namens! Die anderen beiden Core Web Vitals stoppen, nachdem die Hauptkomponente nach dem Laden (für LCP) oder bei der ersten Interaktion (für FID) auf der Seite gefunden wurde. Dies bedeutet, dass unsere traditionellen laborbasierten Tools wie Lighthouse den CLS oft nicht vollständig widerspiegeln, da sie nur den CLS für die Anfangslast berechnen. Im wirklichen Leben scrollt ein Benutzer die Seite nach unten und erhält möglicherweise mehr Inhalt, der zu mehr Verschiebungen führt.

CLS ist auch eine Art künstliche Zahl, die basierend darauf berechnet wird, wie viel von der Seite sich bewegt und wie oft. Während LCP und FID in Millisekunden gemessen werden, ist CLS eine einheitslose Zahl , die durch eine komplexe Berechnung ausgegeben wird. Wir möchten, dass die Seite 0,1 oder weniger beträgt, um dieses Core Web Vital zu bestehen. Alles über 0,25 wird als „schlecht“ angesehen.

Durch Benutzerinteraktion verursachte Verschiebungen werden nicht gezählt . Dies ist definiert als innerhalb von 500 ms nach einer bestimmten Gruppe von Benutzerinteraktionen, obwohl Zeigerereignisse und Bildlauf ausgeschlossen sind. Es wird davon ausgegangen, dass ein Benutzer, der auf eine Schaltfläche klickt, erwarten könnte, dass Inhalte angezeigt werden, beispielsweise durch Erweitern eines reduzierten Abschnitts.

Bei CLS geht es darum , unerwartete Verschiebungen zu messen . Das Scrollen sollte nicht dazu führen, dass sich Inhalte bewegen, wenn eine Seite optimal aufgebaut ist, und ebenso sollte das Bewegen der Maus über ein Produktbild, um beispielsweise eine vergrößerte Version zu erhalten, auch nicht dazu führen, dass die anderen Inhalte herumspringen. Aber es gibt natürlich Ausnahmen und diese Seiten müssen überlegen, wie sie darauf reagieren.

CLS wird auch ständig mit Optimierungen und Fehlerbehebungen weiterentwickelt. Es wurde gerade eine größere Änderung angekündigt, die langlebigen Seiten, wie Single Page Apps (SPA) und unendlich scrollenden Seiten, die viele der Meinung waren, dass sie in CLS zu Unrecht bestraft wurden, etwas Ruhe verschaffen sollte. Anstatt wie bisher Schichten über die gesamte Seitenzeit zu akkumulieren, um den CLS-Score zu berechnen, wird der Score basierend auf dem größten Satz von Schichten innerhalb eines bestimmten Zeitfensters berechnet.

Das bedeutet, dass, wenn Sie drei CLS-Stücke von 0,05, 0,06 und 0,04 haben, dies zuvor als 0,15 aufgezeichnet worden wäre (dh über der „guten“ Grenze von 0,1), während es jetzt als 0,06 bewertet wird. Es ist immer noch kumulativ in dem Sinne, dass der Score aus separaten Verschiebungen innerhalb dieses Zeitrahmens bestehen kann (dh wenn dieser CLS-Score von 0,06 durch drei separate Verschiebungen von 0,02 verursacht wurde), aber er ist einfach nicht mehr über die gesamte Lebensdauer der Seite kumulativ .

Das heißt, wenn Sie die Ursachen für diese Verschiebung um 0,06 lösen, wird Ihr CLS als die nächstgrößte (0,05) gemeldet, sodass es immer noch alle Verschiebungen über die Lebensdauer der Seite betrachtet – es entscheidet sich nur dafür, nur zu melden der größte als der CLS-Score.

Lassen Sie uns nach dieser kurzen Einführung in einige der Methoden von CLS zu einigen der Lösungen übergehen ! Bei all diesen Techniken geht es im Grunde darum, die richtige Menge an Speicherplatz zu reservieren, bevor zusätzlicher Inhalt geladen wird – ob es sich nun um Medien oder mit JavaScript eingefügte Inhalte handelt, aber Webentwicklern stehen einige verschiedene Optionen zur Verfügung, um dies zu tun.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Legen Sie Breite und Höhe für Bilder und iFrames fest

Ich habe bereits darüber geschrieben, aber eine der einfachsten Maßnahmen zur Reduzierung von CLS besteht darin, sicherzustellen, dass die Attribute width und height für Ihre Bilder festgelegt sind . Ohne sie führt ein Bild dazu, dass sich der nachfolgende Inhalt verschiebt, um ihm nach dem Herunterladen Platz zu machen:

Ein Beispiellayout mit einem Titel und zwei Absätzen, wobei der zweite Absatz nach unten verschoben werden muss, um Platz für ein Bild zu schaffen.
Layoutverschiebung nach Laden des Bildes. (Große Vorschau)

Dies ist einfach eine Frage der Änderung Ihres Bild-Markups von:

 <img src="hero_image.jpg" alt="...">

Zu:

 <img src="hero_image.jpg" alt="..." width="400" height="400">

Sie finden die Abmessungen des Bilds, indem Sie DevTools öffnen und den Mauszeiger über das Element bewegen (oder darauf tippen).

Screenshot von Chrome Dev Tools mit Bild, gerenderter Größe, gerendertem Seitenverhältnis, intrinsischer Größe, intrinsischem Seitenverhältnis, Dateigröße und aktueller Quelle.
Chrome DevTools zeigt die Bildabmessungen und Seitenverhältnisse an, wenn Sie den Mauszeiger über ein Element bewegen. (Große Vorschau)

Ich empfehle, die intrinsische Größe (die tatsächliche Größe der Bildquelle) zu verwenden, und der Browser skaliert diese dann auf die gerenderte Größe, wenn Sie CSS verwenden, um diese zu ändern.

Kurztipp : Wenn Sie sich wie ich nicht erinnern können, ob es sich um Breite und Höhe oder Höhe und Breite handelt, stellen Sie es sich als X- und Y-Koordinaten vor, sodass wie bei X die Breite immer zuerst angegeben wird.

Wenn Sie responsive Bilder haben und CSS verwenden, um die Bildabmessungen zu ändern (z. B. um es auf eine max-width von 100 % der Bildschirmgröße zu beschränken), können diese Attribute zur Berechnung der height verwendet werden – vorausgesetzt, Sie denken daran, dies zu überschreiben auto in deinem CSS:

 img { max-width: 100%; height: auto; }

Alle modernen Browser unterstützen dies jetzt, obwohl dies bis vor kurzem nicht der Fall war, wie in meinem Artikel behandelt. Dies funktioniert auch für <picture> -Elemente und srcset Bilder (setzen Sie die width und height im Fallback-Element img ), jedoch noch nicht für Bilder mit unterschiedlichen Seitenverhältnissen — es wird daran gearbeitet, und bis dahin sollten Sie noch width und height festlegen da alle Werte besser sind als die 0 -mal- 0 -Standardwerte!

Dies funktioniert auch bei nativen Lazy-Loaded-Bildern (obwohl Safari standardmäßig noch kein natives Lazy-Loading unterstützt).

Die neue CSS aspect-ratio

Die obige width und height zum Berechnen der Höhe für responsive Bilder kann mithilfe der neuen CSS aspect-ratio , die jetzt von Chromium-basierten Browsern und Firefox unterstützt wird, auf andere Elemente verallgemeinert werden, ist aber auch in Safari Technology Preview so hoffentlich bedeutet das, dass es bald zur stabilen Version kommt.

Sie könnten es also beispielsweise für ein eingebettetes Video im Verhältnis 16: 9 verwenden:

 video { max-width: 100%; height: auto; aspect-ratio: 16 / 9; }
 <video controls width="1600" height="900" poster="..."> <source src="/media/video.webm" type="video/webm"> <source src="/media/video.mp4" type="video/mp4"> Sorry, your browser doesn't support embedded videos. </video>

Ohne die Eigenschaft aspect-ratio zu definieren, ignorieren Browser interessanterweise die Höhe für responsive Videoelemente und verwenden ein Standard-Seitenverhältnis von 2:1, sodass das obige erforderlich ist, um hier eine Layoutverschiebung zu vermeiden.

In Zukunft soll es sogar möglich sein, das aspect-ratio anhand der Elementattribute dynamisch einzustellen, indem man das aspect-ratio: attr(width) / attr(height); aber leider wird dies noch nicht unterstützt.

Oder Sie können sogar das aspect-ratio für ein <div> -Element für eine Art benutzerdefiniertes Steuerelement verwenden, das Sie erstellen, um es reaktionsfähig zu machen:

 #my-square-custom-control { max-width: 100%; height: auto; width: 500px; aspect-ratio: 1; }
 <div></div>

Für die Browser, die das aspect-ratio nicht unterstützen, können Sie den älteren Padding-Bottom-Hack verwenden, aber mit der Einfachheit des neueren aspect-ratio und der breiten Unterstützung (insbesondere wenn dies von Safari Technical Preview zu regulärem Safari wechselt) ist es so schwer, diese ältere Methode zu rechtfertigen.

Chrome ist der einzige Browser, der CLS an Google zurückgibt, und er unterstützt das aspect-ratio Probleme in Bezug auf Core Web Vitals gelöst werden. Ich mag es nicht, den Metriken Vorrang vor den Benutzern zu geben, aber die Tatsache, dass die anderen Chromium- und Firefox-Browser dies haben und Safari hoffentlich bald, und dass dies eine progressive Verbesserung ist, bedeutet, dass ich sagen würde, dass wir an dem Punkt sind, an dem wir sind kann den Padding-Bottom-Hack hinter sich lassen und saubereren Code schreiben.

Machen Sie großzügig Gebrauch von min-height

Für Elemente, die keine responsive Größe, sondern stattdessen eine feste Höhe benötigen, sollten Sie die Verwendung von min-height in Betracht ziehen. Dies könnte zum Beispiel für eine Überschrift mit fester Höhe gelten , und wir können wie gewohnt unterschiedliche Überschriften für die verschiedenen Haltepunkte verwenden, indem wir Medienabfragen verwenden:

 header { min-height: 50px; } @media (min-width: 600px) { header { min-height: 200px; } }
 <header> ... </header>

Dasselbe gilt natürlich für die min-width horizontal platzierter Elemente, aber normalerweise verursacht die Höhe die CLS-Probleme.

Eine fortschrittlichere Technik für eingefügte Inhalte und erweiterte CSS-Selektoren besteht darin, darauf abzuzielen, wenn der erwartete Inhalt noch nicht eingefügt wurde. Zum Beispiel, wenn Sie den folgenden Inhalt hatten:

 <div class="container"> <div class="main-content">...</div> </div>

Und ein zusätzliches div wird über JavaScript eingefügt:

 <div class="container"> <div class="additional-content">.../div> <div class="main-content">...</div> </div>

Dann könnten Sie das folgende Snippet verwenden, um Platz für zusätzlichen Inhalt zu lassen, wenn das main-content Div anfänglich gerendert wird.

 .main-content:first-child { margin-top: 20px; }

Dieser Code erzeugt tatsächlich eine Verschiebung zum main-content , da der Rand als Teil dieses Elements zählt, sodass er sich zu verschieben scheint, wenn er entfernt wird (auch wenn er sich nicht wirklich auf dem Bildschirm bewegt). Zumindest der Inhalt darunter wird jedoch nicht verschoben, sodass CLS reduziert werden sollte.

Alternativ können Sie das Pseudo-Element ::before verwenden, um das Leerzeichen hinzuzufügen, um die Verschiebung auch auf dem main-content zu vermeiden:

 .main-content:first-child::before { content: ''; min-height: 20px; display: block; }

Aber ganz ehrlich, die bessere Lösung ist, das div im HTML zu haben und dafür min-height zu verwenden.

Überprüfen Sie Fallback-Elemente

Ich verwende gerne die progressive Erweiterung, um eine einfache Website bereitzustellen, wenn möglich sogar ohne JavaScript. Unglücklicherweise hat mich dies kürzlich auf einer Website, die ich betreue, erwischt, als die Nicht-JavaScript-Fallback-Version anders war als zu Beginn des JavaScript-Einsatzes.

Das Problem war auf die Menüschaltfläche „Inhaltsverzeichnis“ in der Kopfzeile zurückzuführen. Bevor das JavaScript aktiviert wird, ist dies ein einfacher Link, der so gestaltet ist, dass er wie die Schaltfläche aussieht, die Sie zur Seite mit dem Inhaltsverzeichnis führt. Sobald JavaScript aktiviert wird, wird es zu einem dynamischen Menü , mit dem Sie direkt zu jeder Seite navigieren können, zu der Sie von dieser Seite aus gehen möchten.

Screenshots von zwei Inhaltsverzeichnis-Navigationskomponenten im Stil einer Schaltfläche. Mit JavaScript öffnet dies ein dynamisches Menü, wie im zweiten Bild gezeigt.
Eine Inhaltsverzeichnis-Header-Komponente, die zunächst als einfacher Link (oben) gerendert und dann mit JavaScript zu einem dynamischen Menü (unten) erweitert wird. (Große Vorschau)

Ich habe semantische Elemente verwendet und so ein Ankerelement ( <a href="#table-of-contents"> ) für den Fallback-Link verwendet, aber dieses durch einen <button> für das JavaScript-gesteuerte dynamische Menü ersetzt. Diese wurden so gestaltet, dass sie gleich aussahen, aber der Fallback-Link war ein paar Pixel kleiner als die Schaltfläche!

Dies war so klein, und das JavaScript trat normalerweise so schnell ein, dass ich nicht bemerkt hatte, dass es ausgeschaltet war. Chrome hat es jedoch bei der Berechnung des CLS bemerkt und, da dies in der Kopfzeile stand, die gesamte Seite um ein paar Pixel nach unten verschoben . Das hatte also einen ziemlichen Einfluss auf die CLS-Punktzahl – genug, um alle unsere Seiten in die Kategorie „Verbesserung erforderlich“ zu werfen.

Dies war ein Fehler meinerseits, und die Lösung bestand einfach darin , die beiden Elemente zu synchronisieren (es hätte auch behoben werden können, indem eine min-height für den Header festgelegt wurde, wie oben beschrieben), aber es verwirrte mich ein wenig. Ich bin mir sicher, dass ich nicht der einzige bin, dem dieser Fehler unterlaufen ist, also achten Sie darauf, wie die Seite ohne JavaScript gerendert wird. Glauben Sie nicht, dass Ihre Benutzer JavaScript deaktivieren? Alle Ihre Benutzer verwenden kein JS, während sie Ihr JS herunterladen.

Webfonts verursachen Layoutverschiebungen

Webfonts sind eine weitere häufige Ursache für CLS, da der Browser zunächst den erforderlichen Speicherplatz basierend auf der Fallback-Schriftart berechnet und ihn dann beim Herunterladen der Webschriftart neu berechnet. Normalerweise ist die CLS klein, vorausgesetzt, dass eine ähnlich große Fallback-Schriftart verwendet wird, so dass sie oft nicht genug Probleme verursachen, um Core Web Vitals zum Scheitern zu bringen, aber sie können dennoch für Benutzer verwirrend sein.

Zwei Screenshots eines Smashing Magazine-Artikels mit unterschiedlichen Schriftarten. Der Text hat eine deutlich andere Größe und bei Verwendung der Webfonts kann ein zusätzlicher Satz hineinpassen.
Smashing Magazine-Artikel mit Fallback-Font und mit vollständigen Web-Fonts. (Große Vorschau)

Leider hilft auch das Vorladen der Webfonts hier nicht, da dies zwar die Zeit verkürzt, für die die Fallback-Schriftarten verwendet werden (was gut für die Ladeleistung ist – LCP), aber dennoch Zeit braucht, um sie abzurufen , und daher werden die Fallbacks weiterhin verwendet durch den Browser in den meisten Fällen und vermeidet CLS daher nicht. Wenn Sie wissen, dass auf der nächsten Seite eine Webschriftart benötigt wird (sagen wir, Sie befinden sich auf einer Anmeldeseite und wissen, dass die nächste Seite eine spezielle Schriftart verwendet), können Sie diese vorab abrufen.

Um schriftbedingte Layoutverschiebungen insgesamt zu vermeiden, könnten wir natürlich überhaupt keine Webschriftarten verwenden – einschließlich der Verwendung von Systemschriftarten oder der Verwendung von font-display: optional , um sie nicht zu verwenden, wenn sie nicht rechtzeitig für das anfängliche Rendern heruntergeladen werden. Aber beides ist nicht sehr zufriedenstellend, um ehrlich zu sein.

Eine andere Möglichkeit besteht darin, sicherzustellen, dass die Abschnitte die richtige Größe haben (z. B. mit min-height ), damit der Text darin zwar etwas verschoben werden kann, der Inhalt darunter jedoch nicht nach unten gedrückt wird, selbst wenn dies geschieht. Beispielsweise könnte das Festlegen einer min-height für das Element <h1> verhindern, dass der gesamte Artikel nach unten verschoben wird, wenn etwas größere Schriftarten geladen werden – vorausgesetzt, die unterschiedlichen Schriftarten verursachen keine unterschiedliche Anzahl von Zeilen. Dadurch werden die Auswirkungen der Verschiebungen verringert, jedoch wird es für viele Anwendungsfälle (z. B. generische Absätze) schwierig sein, eine Mindesthöhe zu verallgemeinern.

Worüber ich mich am meisten freue, dieses Problem zu lösen, sind die neuen CSS-Schriftdeskriptoren, mit denen Sie Fallback-Schriftarten in CSS einfacher anpassen können:

 @font-face { font-family: 'Lato'; src: url('/static/fonts/Lato.woff2') format('woff2'); font-weight: 400; } @font-face { font-family: "Lato-fallback"; size-adjust: 97.38%; ascent-override: 99%; src: local("Arial"); } h1 { font-family: Lato, Lato-fallback, sans-serif; }

Zuvor war das Anpassen der erforderlichen Fallback-Schriftart mithilfe der Font Loading API in JavaScript komplizierter, aber diese Option, die sehr bald verfügbar sein wird, könnte uns endlich eine einfachere Lösung bieten, die mit größerer Wahrscheinlichkeit an Boden gewinnt. Weitere Informationen zu dieser bevorstehenden Innovation und weitere Ressourcen dazu finden Sie in meinem vorherigen Artikel zu diesem Thema.

Anfängliche Vorlagen für clientseitig gerenderte Seiten

Viele clientseitig gerenderte Seiten oder Einzelseiten-Apps rendern eine anfängliche Basisseite nur mit HTML und CSS und „hydrieren“ dann die Vorlage, nachdem das JavaScript heruntergeladen und ausgeführt wurde.

Es ist leicht, dass diese anfänglichen Vorlagen nicht mehr mit der JavaScript-Version synchron sind, da neue Komponenten und Funktionen der App in JavaScript hinzugefügt werden, aber nicht der anfänglichen HTML-Vorlage hinzugefügt werden, die zuerst gerendert wird. Dies verursacht dann CLS, wenn diese Komponenten von JavaScript injiziert werden.

Überprüfen Sie also alle Ihre anfänglichen Vorlagen , um sicherzustellen, dass sie immer noch gute anfängliche Platzhalter sind. Und wenn die anfängliche Vorlage aus leeren <div> s besteht, verwenden Sie die obigen Techniken, um sicherzustellen, dass sie die richtige Größe haben, um Verschiebungen zu vermeiden.

Darüber hinaus sollte das anfängliche div , das mit der App injiziert wird, eine min-height haben, um zu vermeiden, dass es anfänglich mit einer Höhe von 0 gerendert wird, bevor die ursprüngliche Vorlage überhaupt eingefügt wird.

 <div></div>

Solange die min-height größer als die meisten Viewports ist, sollte dies beispielsweise jegliches CLS für den Website-Footer vermeiden. CLS wird nur gemessen, wenn es sich im Ansichtsfenster befindet, und wirkt sich daher auf den Benutzer aus. Standardmäßig hat ein leeres div eine Höhe von 0 Pixel. Geben Sie ihm also eine min-height , die näher an der tatsächlichen Höhe liegt, wenn die App geladen wird.

Stellen Sie sicher, dass Benutzerinteraktionen innerhalb von 500 ms abgeschlossen sind

Benutzerinteraktionen, die zu einer Verschiebung des Inhalts führen, werden von den CLS-Bewertungen ausgeschlossen. Diese sind auf 500 ms nach der Interaktion beschränkt. Wenn Sie also auf eine Schaltfläche klicken und eine komplexe Verarbeitung durchführen, die über 500 ms dauert, und dann neue Inhalte rendern, wird Ihr CLS-Score darunter leiden.

Sie können sehen, ob die Schicht in Chrome DevTools ausgeschlossen wurde, indem Sie die Seite auf der Registerkarte Leistung aufzeichnen und dann die Schichten finden, wie im nächsten Screenshot gezeigt. Öffnen Sie DevTools, gehen Sie zur sehr einschüchternden (aber sehr nützlichen, sobald Sie einen Dreh raus haben!) Registerkarte Leistung und klicken Sie dann auf die Aufnahmeschaltfläche oben links (im Bild unten eingekreist) und interagieren Sie mit Ihrer Seite und stoppen Sie die Aufnahme einmal Komplett.

Screenshot von Chrome Dev Tools mit einer ausgewählten Schicht und der Zusammenfassung davon zeigt, dass es kürzlich Eingaben gab und die Schicht daher nicht in der kumulativen Punktzahl enthalten ist.
Verwenden Sie die Registerkarte „Leistung“ in den Chrome-Entwicklungstools, um zu sehen, ob Verschiebungen aufgrund kürzlich erfolgter Eingaben ausgeschlossen sind. (Große Vorschau)

Sie werden einen Filmstreifen der Seite sehen, auf der ich einige der Kommentare zu einem anderen Smashing Magazine-Artikel geladen habe, sodass Sie in dem Teil, den ich eingekreist habe, gerade noch erkennen können, wie die Kommentare geladen werden und die rote Fußzeile außerhalb des Bildschirms nach unten verschoben wird. Weiter unten auf der Registerkarte " Leistung " unter der Zeile " Erfahrung " fügt Chrome jeder Schicht ein rötlich-rosa Kästchen hinzu. Wenn Sie darauf klicken, erhalten Sie weitere Details auf der Registerkarte " Zusammenfassung " unten.

Hier können Sie sehen, dass wir einen massiven Wert von 0,3359 erreicht haben – weit über dem Schwellenwert von 0,1, den wir unterschreiten wollen, aber der kumulierte Wert hat dies nicht berücksichtigt, da „ Hatte kürzliche Eingabe “ auf „Verwendet“ gesetzt ist.

Das Sicherstellen, dass Interaktionen den Inhalt nur innerhalb von 500 ms verschieben, grenzt an das, was First Input Delay zu messen versucht, aber es gibt Fälle, in denen der Benutzer sehen kann, dass die Eingabe eine Wirkung hatte (z erst nach der 500-ms-Grenze zur Seite hinzugefügt werden, also ist CLS schlecht.

Idealerweise ist die gesamte Interaktion innerhalb von 500 ms abgeschlossen, aber Sie können einige Dinge tun, um den erforderlichen Platz mit den oben genannten Techniken freizuhalten, während diese Verarbeitung läuft, sodass Sie, wenn es länger als die magischen 500 ms dauert, fertig sind die Schicht bereits bewältigt haben und daher nicht dafür bestraft werden. Dies ist besonders nützlich, wenn Sie Inhalte aus dem Netzwerk abrufen, die variabel sein und außerhalb Ihrer Kontrolle liegen könnten.

Andere Punkte, auf die Sie achten sollten, sind Animationen , die länger als 500 ms dauern und sich daher auf CLS auswirken können. Dies mag zwar etwas restriktiv erscheinen, aber das Ziel von CLS besteht nicht darin, den „Spaß“ einzuschränken, sondern angemessene Erwartungen an die Benutzererfahrung zu setzen, und ich denke nicht, dass es unrealistisch ist, zu erwarten, dass dies 500 ms oder weniger dauert. Aber wenn Sie anderer Meinung sind oder einen Anwendungsfall haben, den sie möglicherweise nicht berücksichtigt haben, ist das Chrome-Team offen für Feedback dazu.

Synchrones JavaScript

Die letzte Technik, die ich besprechen werde, ist ein wenig umstritten, da sie gegen bekannte Ratschläge zur Webleistung verstößt, aber in bestimmten Situationen kann sie die einzige Methode sein. Wenn Sie Inhalte haben, von denen Sie wissen, dass sie Verschiebungen verursachen, besteht eine Lösung zur Vermeidung der Verschiebungen darin, sie nicht zu rendern, bis sie sich beruhigt haben!

Der folgende HTML-Code blendet das div anfangs aus, lädt dann etwas renderblockierendes JavaScript, um das div zu füllen, und blendet es dann wieder ein. Da das JavaScript Render-Blocking ist, wird nichts darunter gerendert (einschließlich des zweiten style , um ihn einzublenden), sodass keine Verschiebungen auftreten.

 <style> .cls-inducing-div { display: none; } </style> <div class="cls-inducing-div"></div> <script> ... </script> <style> .cls-inducing-div { display: block; } </style>

Es ist wichtig, das CSS bei dieser Technik in den HTML- Code einzubetten, damit es der Reihe nach angewendet wird. Die Alternative besteht darin, den Inhalt mit JavaScript selbst einzublenden, aber was mir an der obigen Technik gefällt, ist, dass der Inhalt auch dann eingeblendet wird, wenn das JavaScript fehlschlägt oder vom Browser deaktiviert wird.

Diese Technik kann auch mit externem JavaScript angewendet werden, dies verursacht jedoch mehr Verzögerung als ein Inline- script , da das externe JavaScript angefordert und heruntergeladen wird. Diese Verzögerung kann minimiert werden, indem die JavaScript-Ressource vorab geladen wird, damit sie schneller verfügbar ist, sobald der Parser diesen Codeabschnitt erreicht:

 <head> ... <link rel="preload" href="cls-inducing-javascript.js" as="script"> ... </head> <body> ... <style> .cls-inducing-div { display: none; } </style> <div class="cls-inducing-div"></div> <script src="cls-inducing-javascript.js"></script> <style> .cls-inducing-div { display: block; } </style> ... </body>

Nun, wie ich schon sagte, ich bin sicher, dass dies einige Web-Performance-Leute zusammenzucken lässt, da der Rat lautet, async, defer oder das neuere type="module" (die standardmäßig defer -ed sind) für JavaScript zu verwenden, um Blockierungen zu vermeiden render , während wir hier das Gegenteil tun! Wenn der Inhalt jedoch nicht vorherbestimmt werden kann und erschütternde Verschiebungen verursachen wird, dann macht es wenig Sinn, ihn früh zu rendern.

Ich habe diese Technik für ein Cookie-Banner verwendet, das oben auf der Seite geladen wurde und den Inhalt nach unten verschoben hat:

Ein Screenshot einer Webseite, bei der der Inhalt nach unten verschoben wird, wenn oben auf der Seite ein Cookie-Banner hinzugefügt wird.
Ein Cookie-Hinweis oben auf der Seite oder ein anderes Banner kann den Inhalt nach unten verschieben. (Große Vorschau)

Dies erforderte das Lesen eines Cookies, um zu sehen, ob das Cookie-Banner angezeigt werden sollte oder nicht, und obwohl dies serverseitig abgeschlossen werden konnte, war dies eine statische Site ohne die Möglichkeit, das zurückgegebene HTML dynamisch zu ändern.

Cookie-Banner können auf verschiedene Arten implementiert werden, um CLS zu vermeiden. Zum Beispiel, indem Sie sie unten auf der Seite platzieren oder sie über den Inhalt legen, anstatt den Inhalt nach unten zu verschieben. Wir haben es vorgezogen, den Inhalt oben auf der Seite zu halten, also mussten wir diese Technik verwenden, um die Verschiebungen zu vermeiden. Es gibt verschiedene andere Warnungen und Banner, die Websitebesitzer aus verschiedenen Gründen möglicherweise lieber oben auf der Seite sehen möchten.

Ich habe diese Technik auch auf einer anderen Seite verwendet, auf der JavaScript Inhalte in „Haupt“- und „Neben“-Spalten verschiebt (aus Gründen, auf die ich nicht näher eingehen werde, war es nicht möglich, dies richtig in HTML-Serverseite zu konstruieren). Das erneute Ausblenden des Inhalts, bis das JavaScript den Inhalt neu angeordnet hatte, und erst dann das Anzeigen vermied die CLS-Probleme, die den CLS-Score dieser Seiten nach unten zogen. Und wieder wird der Inhalt automatisch eingeblendet, auch wenn das JavaScript aus irgendeinem Grund nicht ausgeführt wird, und der unverschobene Inhalt wird angezeigt.

Die Verwendung dieser Technik kann sich auf andere Metriken (insbesondere LCP und auch First Contentful Paint) auswirken, da Sie das Rendern verzögern und möglicherweise auch den Look-Ahead-Preloader von Browsern blockieren, aber es ist ein weiteres Tool, das Sie für Fälle in Betracht ziehen sollten, in denen keine andere Option besteht.

Fazit

Die kumulative Layoutverschiebung wird durch Inhaltsänderungsdimensionen oder durch spät ausgeführtes JavaScript verursacht, das neue Inhalte in die Seite einfügt. In diesem Beitrag haben wir verschiedene Tipps und Tricks besprochen, um dies zu vermeiden. Ich bin froh, dass die Core Web Vitals dieses irritierende Thema ins Rampenlicht gerückt haben – zu lange haben wir Webentwickler (und ich zähle mich definitiv dazu) dieses Problem ignoriert.

Die Bereinigung meiner eigenen Websites hat zu einer besseren Erfahrung für alle Besucher geführt. Ich ermutige Sie, sich auch Ihre CLS-Probleme anzusehen , und hoffentlich sind einige dieser Tipps hilfreich, wenn Sie dies tun. Wer weiß, vielleicht schaffen Sie es sogar, für alle Ihre Seiten den schwer fassbaren CLS-Wert von 0 zu erreichen!

Mehr Ressourcen

  • Core Web Vitals-Artikel hier im Smashing Magazine, einschließlich meiner eigenen zum Festlegen von Breite und Höhe von Bildern, Messen von Core Web Vitals und CSS-Schriftdeskriptoren.
  • Googles Core Web Vitals-Dokumentation einschließlich ihrer Seite zu CLS.
  • Weitere Details zur jüngsten Änderung an CLS und dann wurde diese Änderung in verschiedenen Google-Tools aktualisiert.
  • Das CLS-Änderungsprotokoll mit detaillierten Änderungen in jeder Version von Chrome.
  • Der fast vollständige Leitfaden zur kumulativen Layoutverschiebung von Jess Peck.
  • Kumulative Layoutverschiebung: Visuelle Instabilität messen und vermeiden von Karolina Szczur.
  • Ein Layout-Shift-GIF-Generator, der dabei hilft, gemeinsam nutzbare Demonstrationen von CLS zu erstellen.