content-sichtbarkeit: die neue CSS-Eigenschaft zur Steigerung der Rendering-Leistung

Verbessern Sie die anfängliche Ladezeit, indem Sie das Rendern von nicht sichtbaren Inhalten überspringen.

Vladimir Levin
Vladimir Levin

Veröffentlicht: 5. August 2020

Mit der Property content-visibility kann der User-Agent das Rendern eines Elements, einschließlich Layout und Painting, überspringen, bis es benötigt wird. Da das Rendering übersprungen wird, ist die anfängliche Nutzerauslieferung mit der content-visibility-Eigenschaft viel schneller, wenn ein großer Teil Ihrer Inhalte nicht auf dem Bildschirm zu sehen ist. Außerdem können Sie so schneller mit den Inhalten auf dem Bildschirm interagieren. Ziemlich cool.

Unterstützte Browser

  • Chrome: 85.
  • Edge: 85.
  • Firefox: 125
  • Safari: 18.

Quelle

Demo mit Zahlen, die Netzwerkergebnisse darstellen
In unserer Artikeldemo führt die Anwendung von content-visibility: auto auf gechunkte Inhaltsbereiche zu einer 7-fachen Steigerung der Renderingleistung beim ersten Laden. Weitere Informationen finden Sie weiter unten.

CSS-Begrenzung

Das Haupt- und übergeordnete Ziel der CSS-Begrenzung besteht darin, die Renderleistung von Webinhalten zu verbessern, indem ein DOM-Unterbaum vorhersehbar vom Rest der Seite isoliert wird.

Im Grunde kann ein Entwickler einem Browser mitteilen, welche Teile der Seite als Inhaltssatz gekapselt sind. So können die Browser den Inhalt analysieren, ohne den Status außerhalb des untergeordneten Baums berücksichtigen zu müssen. Wenn der Browser weiß, welche Inhaltselemente (untergeordnete Bäume) isolierte Inhalte enthalten, kann er Optimierungsentscheidungen für das Seiten-Rendering treffen.

Es gibt vier Arten von CSS-Begrenzungen, die jeweils ein potenzieller Wert für die CSS-Property contain sind. Sie können in einer durch Leerzeichen getrennten Liste von Werten kombiniert werden:

  • size: Durch die Größenbeschränkung eines Elements wird sichergestellt, dass der Rahmen des Elements dargestellt werden kann, ohne die Nachfolgerelemente untersuchen zu müssen. Das bedeutet, dass wir das Layout der untergeordneten Elemente möglicherweise überspringen können, wenn wir nur die Größe des Elements benötigen.
  • layout: Layout-Begrenzung bedeutet, dass die Nachfolgerelemente das externe Layout anderer Felder auf der Seite nicht beeinflussen. So können wir das Layout der untergeordneten Elemente möglicherweise überspringen, wenn wir nur andere Felder ausrichten möchten.
  • style: Durch die Stilbegrenzung wird verhindert, dass Eigenschaften, die sich nicht nur auf die Nachkommen auswirken, das Element verlassen (z.B. Zähler). So können wir die Stilberechnung für die Nachkommen möglicherweise überspringen, wenn wir nur Stile für andere Elemente berechnen möchten.
  • paint: Die Farbeindämmung sorgt dafür, dass die Nachfolgerelemente der enthaltenen Box nicht außerhalb ihrer Grenzen angezeigt werden. Nichts darf das Element sichtbar überlaufen. Wenn ein Element nicht auf dem Bildschirm oder anderweitig nicht sichtbar ist, sind auch seine untergeordneten Elemente nicht sichtbar. So können wir das Zeichnen der Nachkommen möglicherweise überspringen, wenn sich das Element außerhalb des Bildschirms befindet.

Rendering-Aufgaben mit content-visibility überspringen

Es kann schwierig sein, die zu verwendenden Begrenzungswerte zu bestimmen, da Browseroptimierungen möglicherweise nur Erfolg haben, wenn ein entsprechender Satz angegeben ist. Sie können mit den Werten experimentieren, um herauszufinden, was am besten funktioniert. Mit content-visibility können Sie die erforderliche Begrenzung auch automatisch anwenden. Mit content-visibility können Sie mit minimalem Aufwand für Sie als Entwickler die größtmögliche Leistungssteigerung mit dem Browser erzielen.

Für das Attribut „content-visibility“ sind mehrere Werte zulässig. Mit auto lassen sich jedoch sofort Leistungsverbesserungen erzielen. Ein Element mit content-visibility: auto erhält die Begrenzungen layout, style und paint. Wenn sich das Element außerhalb des Bildschirms befindet (und nicht anderweitig für den Nutzer relevant ist – relevante Elemente sind solche, die im untergeordneten Knoten den Fokus oder die Auswahl haben), wird es ebenfalls in size eingeschlossen (und der Inhalt wird nicht mehr gerendert und auf Treffer geprüft).

Was bedeutet das? Kurz gesagt: Wenn sich das Element außerhalb des Bildschirms befindet, werden seine Nachkommen nicht gerendert. Der Browser bestimmt die Größe des Elements, ohne den Inhalt zu berücksichtigen. Der Großteil des Renderings, z. B. das Styling und das Layout des untergeordneten Elements, wird übersprungen.

Wenn sich das Element dem Darstellungsbereich nähert, fügt der Browser die size-Begrenzung nicht mehr hinzu und beginnt, den Inhalt des Elements zu zeichnen und zu prüfen. So kann das Rendering genau dann erfolgen, wenn es für den Nutzer sichtbar ist.

Hinweis zur Barrierefreiheit

Eine der Funktionen von content-visibility: auto ist, dass die nicht sichtbaren Inhalte im Dokumentobjektmodell und daher im Baum für Barrierefreiheit verfügbar bleiben (im Gegensatz zu visibility: hidden). Das bedeutet, dass Inhalte auf der Seite gesucht und aufgerufen werden können, ohne auf das Laden warten oder die Renderleistung beeinträchtigen zu müssen.

Die Kehrseite davon ist jedoch, dass Markierungselemente mit Stilelementen wie display: none oder visibility: hidden auch im Bedienungshilfen-Baum erscheinen, wenn sie nicht auf dem Bildschirm zu sehen sind, da der Browser diese Stile erst rendert, wenn sie in den Darstellungsbereich gelangen. Damit diese in der Baumstruktur für Bedienungshilfen nicht zu sehen sind und dadurch zu Unübersichtlichkeit führen, solltest du auch aria-hidden="true" hinzufügen.

Beispiel: Reiseblog

In diesem Beispiel legen wir unseren Reiseblog rechts als Baseline fest und wenden content-visibility: auto auf die segmentierten Bereiche links an. Die Ergebnisse zeigen, dass die Renderingzeiten beim ersten Laden der Seite von 232 ms auf 30 ms gesunken sind.

Ein Reiseblog enthält in der Regel eine Reihe von Geschichten mit einigen Bildern und beschreibendem Text. In einem typischen Browser passiert Folgendes, wenn ein Reiseblog aufgerufen wird:

  1. Ein Teil der Seite wird zusammen mit allen erforderlichen Ressourcen aus dem Netzwerk heruntergeladen.
  2. Der Browser gestaltet den gesamten Inhalt der Seite, ohne zu berücksichtigen, ob er für den Nutzer sichtbar ist.
  3. Der Browser kehrt zu Schritt 1 zurück, bis alle Seite und alle Ressourcen heruntergeladen sind.

In Schritt 2 verarbeitet der Browser den gesamten Inhalt und sucht nach Elementen, die sich möglicherweise geändert haben. Dadurch werden der Stil und das Layout aller neuen Elemente sowie der Elemente aktualisiert, die sich aufgrund neuer Updates möglicherweise verschoben haben. Das ist ein Rendervorgang. Das dauert seine Zeit.

Screenshot eines Reiseblogs
Beispiel für einen Reiseblog. Siehe Demo auf Codepen

Sehen wir uns nun an, was passiert, wenn Sie content-visibility: auto auf jede der einzelnen Geschichten im Blog setzen. Die allgemeine Schleife ist dieselbe: Der Browser lädt Teile der Seite herunter und rendert sie. Der Unterschied besteht jedoch in der Arbeitsmenge, die in Schritt 2 ausgeführt wird.

Mit der Option „Inhaltssichtbarkeit“ werden alle Inhalte gestaltet und angeordnet, die derzeit für den Nutzer sichtbar sind (sie sind auf dem Bildschirm). Bei der Verarbeitung einer Story, die sich vollständig außerhalb des Bildschirms befindet, überspringt der Browser jedoch das Rendering und ordnet nur das Elementfeld selbst einen Stil zu und legt das Layout fest.

Das Laden dieser Seite würde so lange dauern, als wären alle Storys auf dem Bildschirm zu sehen und die Bereiche für die Storys, die nicht auf dem Bildschirm zu sehen sind, leer. Dies führt zu einer deutlich besseren Leistung, da die Renderingkosten beim Laden um mindestens 50 % reduziert werden. In unserem Beispiel wurde die Renderingzeit von 232 ms auf 30 ms reduziert. Das entspricht einer 7-fachen Leistungssteigerung.

Welche Arbeit müssen Sie leisten, um von diesen Vorteilen zu profitieren? Zuerst teilen wir den Inhalt in Abschnitte auf:

Ein kommentierter Screenshot, der zeigt, wie Inhalte mit einer CSS-Klasse in Abschnitte unterteilt werden.
Beispiel für das Aufteilen von Inhalten in Abschnitte mit der Klasse story, um content-visibility: auto zu erhalten. Demo auf Codepen ansehen

Anschließend wenden wir die folgende Stilregel auf die Abschnitte an:

.story {
  content-visibility: auto;
  contain-intrinsic-size: 1000px; /* Explained in the next section. */
}

Natürliche Größe eines Elements mit contain-intrinsic-size angeben

Damit die potenziellen Vorteile von content-visibility genutzt werden können, muss der Browser die Größe begrenzen, damit sich die Renderingergebnisse des Inhalts nicht auf die Größe des Elements auswirken. Das Element wird dann so dargestellt, als wäre es leer. Wenn für das Element in einem regulären Blocklayout keine Höhe angegeben ist, hat es eine Höhe von 0.

Das ist möglicherweise nicht ideal, da sich die Größe der Bildlaufleiste ändert, da jede Story eine nicht nullwertige Höhe haben muss.

Glücklicherweise bietet CSS eine weitere Property, contain-intrinsic-size, mit der die natürliche Größe des Elements effektiv angegeben wird, wenn das Element von der Begrenzung der Größe betroffen ist. In unserem Beispiel legen wir 1000px als Schätzung für die Höhe und Breite der Abschnitte fest.

Das bedeutet, dass es so dargestellt wird, als hätte es ein einzelnes untergeordnetes Element mit den Dimensionen „intrinsic-size“, sodass Ihre divs ohne Größe weiterhin Platz belegen. contain-intrinsic-size dient als Platzhaltergröße anstelle von gerenderten Inhalten.

Das Keyword auto für contain-intrinsic-size bewirkt, dass der Browser die zuletzt gerenderte Größe (falls vorhanden) speichert und anstelle der vom Entwickler bereitgestellten Platzhaltergröße verwendet. Wenn Sie beispielsweise contain-intrinsic-size: auto 300px angeben, hat das Element zu Beginn eine 300px-eigentliche Größe in jeder Dimension. Sobald der Inhalt des Elements gerendert wurde, behält es jedoch die gerenderte Eigengröße bei. Alle nachfolgenden Änderungen an der Rendering-Größe werden ebenfalls gespeichert. In der Praxis bedeutet dies, dass, wenn Sie ein Element mit angewendetem content-visibility: auto scrollen und dann aus dem sichtbaren Bereich des Elements scrollen, automatisch seine ideale Breite und Höhe beibehalten wird und die Platzhaltergröße nicht wiederhergestellt wird. Diese Funktion ist besonders nützlich für unendliche Scroller, die jetzt automatisch die Größenschätzung mit der Zeit verbessern können, wenn der Nutzer die Seite erkundet.

Inhalte mit content-visibility: hidden ausblenden

Was ist, wenn Sie die Inhalte unabhängig davon, ob sie auf dem Bildschirm angezeigt werden, nicht gerendert lassen möchten, und gleichzeitig die Vorteile des gecachten Rendering-Status nutzen möchten? Geben Sie Folgendes ein: content-visibility: hidden.

Das Attribut content-visibility: hidden bietet dieselben Vorteile von nicht gerenderten Inhalten und einem im Cache gespeicherten Renderingstatus wie content-visibility: auto außerhalb des Bildschirms. Im Gegensatz zu auto wird das Bild jedoch nicht automatisch auf dem Bildschirm gerendert.

So haben Sie mehr Kontrolle und können den Inhalt eines Elements ausblenden und später schnell wieder einblenden.

Vergleichen Sie dies mit anderen gängigen Methoden zum Ausblenden des Inhalts von Elementen:

  • display: none: Das Element wird ausgeblendet und sein Rendering-Status wird gelöscht. Das bedeutet, dass das Entfernen der Ausblendung des Elements genauso teuer ist wie das Rendern eines neuen Elements mit demselben Inhalt.
  • visibility: hidden: Das Element wird ausgeblendet und der Rendering-Status bleibt erhalten. Das Element wird dadurch nicht wirklich aus dem Dokument entfernt, da es (und sein untergeordneter Knoten) weiterhin geometrischen Raum auf der Seite einnimmt und weiterhin angeklickt werden kann. Außerdem wird der Rendering-Status bei Bedarf aktualisiert, auch wenn das Element ausgeblendet ist.

Mit content-visibility: hidden wird das Element dagegen ausgeblendet, während der Rendering-Status beibehalten wird. Wenn also Änderungen erforderlich sind, werden sie erst vorgenommen, wenn das Element wieder angezeigt wird (d. h. die content-visibility: hidden-Property entfernt wird).

Gute Anwendungsfälle für content-visibility: hidden sind die Implementierung erweiterter virtueller Bildlaufleisten und das Layout-Messen. Sie eignen sich auch hervorragend für Single-Page-Anwendungen (SPA). Inaktive App-Ansichten können im DOM verbleiben, wobei content-visibility: hidden angewendet wird, um ihre Anzeige zu verhindern, aber ihren im Cache gespeicherten Status beizubehalten. Dadurch kann die Ansicht schnell gerendert werden, wenn sie wieder aktiv wird.

Auswirkungen auf „Interaction to Next Paint“ (INP)

INP ist ein Messwert, mit dem die Fähigkeit einer Seite bewertet wird, zuverlässig auf Nutzereingaben zu reagieren. Die Reaktionsfähigkeit kann durch eine übermäßige Arbeitslast im Hauptthread beeinträchtigt werden, einschließlich Rendering-Arbeiten.

Wenn Sie die Rendering-Arbeit auf einer bestimmten Seite reduzieren können, haben Sie die Möglichkeit, dass der Haupt-Thread schneller auf Nutzereingaben reagiert. Dazu gehört auch das Rendering. Die Verwendung der CSS-Eigenschaft content-visiblity kann das Rendering reduzieren, insbesondere beim Start, wenn die meisten Rendering- und Layoutarbeiten ausgeführt werden.

Eine Verringerung der Rendering-Arbeit hat direkte Auswirkungen auf die INP. Wenn Nutzer versuchen, mit einer Seite zu interagieren, die die Eigenschaft content-visibility korrekt verwendet, um das Layout und das Rendern nicht sichtbarer Elemente zu verschieben, gibst du dem Hauptthread die Möglichkeit, auf wichtige für den Nutzer sichtbare Arbeit zu reagieren. Dadurch kann der INP-Wert deiner Seite in einigen Situationen verbessert werden.

Fazit

content-visibility und die CSS-Begrenzungsspezifikation sorgen für eine Leistungssteigerung Ihrer CSS-Datei. Weitere Informationen zu diesen Eigenschaften finden Sie hier: