content-visibility: Lange Seiten performant rendern
AI generated
{ }
@
CSS · Rendering Performance · Web Performance
content-visibility: Lange Seiten performant rendern
Rendering-Arbeit sparen, ohne Inhalte zu verlieren

Lange Produktlisten, Artikel-Feeds und Dokumentationsseiten zwingen den Browser, Layout und Style für tausende Elemente zu berechnen, auch wenn davon nur ein Bruchteil sichtbar ist. content-visibility überspringt diese Arbeit gezielt für Bereiche außerhalb des Viewports und macht aus einer trägen langen Seite eine Seite, die sich anfühlt wie eine kurze.

14 Min. Lesezeit content-visibility · contain-intrinsic-size · Rendering Chrome · Edge · Firefox 125+ · Safari 18+

1. Warum lange Seiten das Rendering ausbremsen

Ein Browser berechnet für jedes Element im Dokument Style, Layout und in vielen Fällen auch Paint, unabhängig davon, ob das Element gerade im sichtbaren Bereich liegt. Bei einer Seite mit fünfzig Elementen fällt das nicht auf. Bei einer Produktliste mit zweitausend Karten, einem Kommentarbereich mit hunderten Einträgen oder einer langen technischen Dokumentation summiert sich diese Arbeit zu spürbaren Verzögerungen beim ersten Rendern und bei jedem Reflow. Genau hier setzt content-visibility an: die Eigenschaft erlaubt dem Browser, Rendering-Arbeit für Inhalte außerhalb des Viewports komplett zu überspringen, bis sie tatsächlich gebraucht werden.

Der entscheidende Unterschied zu klassischem Lazy Loading ist, dass content-visibility nicht das Laden von Daten verzögert, sondern die Rendering-Pipeline selbst entlastet. Der DOM-Knoten existiert weiterhin, sein Inhalt ist im Accessibility Tree vorhanden, aber Layout und Paint werden erst berechnet, wenn der Bereich in den Viewport gelangt. Für Seiten mit hunderten oder tausenden Elementen ist das oft der wirkungsvollste einzelne Hebel, um Time to Interactive und Scroll-Performance zu verbessern, ohne die Struktur der Seite zu verändern.

2. Die Werte von content-visibility im Detail

Die Eigenschaft content-visibility kennt drei relevante Werte: visible, hidden und auto. visible ist der Standardwert und verändert nichts, das Element wird ganz normal gerendert. hidden entfernt den Inhalt komplett aus dem Rendering, ähnlich wie display: none, behält aber im Gegensatz dazu den internen Zustand des Elements bei, etwa Scrollpositionen in verschachtelten Containern oder Formulareingaben. Der wichtigste Wert für Performance-Optimierung ist auto: der Browser entscheidet selbst, ob ein Element gerendert wird, basierend darauf, ob es sich im oder nahe am sichtbaren Bereich befindet.

Mit content-visibility: auto überspringt der Browser für Elemente außerhalb des Viewports Layout, Paint und in vielen Fällen auch die Style-Neuberechnung, behält aber die Größe des Elements näherungsweise bei, damit die Scrollbar-Höhe und die Position anderer Elemente stabil bleiben. Sobald das Element in die Nähe des Viewports scrollt, rendert der Browser es normal, meist bevor es tatsächlich sichtbar wird, sodass kein sichtbares Popping entsteht. Diese Kombination aus übersprungener Arbeit und automatischer Reaktivierung macht content-visibility: auto zur zentralen Eigenschaft für lange Listen, Feeds und Dokumentseiten.


/* Basic content-visibility setup for a long feed of cards */
.feed-item {
  content-visibility: auto;
  /* Reserve space so scrollbar height stays stable
     before the browser has ever rendered this item */
  contain-intrinsic-size: auto 320px;
}

/* content-visibility: hidden keeps internal state,
   unlike display: none which resets it completely */
.tab-panel[data-active="false"] {
  content-visibility: hidden;
}

.tab-panel[data-active="true"] {
  content-visibility: visible;
}

3. contain-intrinsic-size: Layout-Sprünge verhindern

Ohne eine Größenangabe schrumpft ein Element mit content-visibility: auto im nicht gerenderten Zustand auf null Höhe, weil der Browser keine Layout-Berechnung durchführt und somit keine natürliche Größe kennt. Das Ergebnis wäre eine springende Scrollbar und ein instabiles Layout, sobald Elemente rein und raus gerendert werden. Die Eigenschaft contain-intrinsic-size löst dieses Problem, indem sie eine Platzhaltergröße definiert, die der Browser verwendet, solange der eigentliche Inhalt nicht gerendert wird.

Der Wert contain-intrinsic-size: auto 320px kombiniert zwei Verhaltensweisen: das Schlüsselwort auto sorgt dafür, dass sich der Browser die zuletzt gerenderte tatsächliche Größe merkt und beim erneuten Verstecken diese Größe statt eines festen Werts verwendet, der feste Pixelwert dient nur als initialer Fallback vor dem ersten Rendern. Für Karten mit stark unterschiedlichen Höhen, etwa Kommentare mit variabler Textlänge, ist diese Kombination deutlich robuster als ein einzelner fester Wert, weil sie sich nach dem ersten Durchlauf an die reale Höhe jedes einzelnen Elements anpasst und so Layout-Sprünge auf ein Minimum reduziert.

4. Praxisbeispiel: Feed mit hunderten Karten

In einem typischen Anwendungsfall, einem News-Feed oder einer Produktübersicht mit mehreren hundert Karten, wird content-visibility: auto direkt auf die einzelnen Karten-Container angewendet, nicht auf die gesamte Liste. Jede Karte bekommt zusätzlich eine geschätzte Höhe über contain-intrinsic-size, idealerweise abgeleitet aus dem Durchschnitt bereits gerenderter Karten desselben Typs. Für einen Feed mit gemischten Karten-Typen, etwa Text-Posts und Bild-Posts, empfiehlt sich eine unterschiedliche Höhenschätzung pro Typ, damit die anfängliche Layout-Verschiebung beim ersten Rendern möglichst klein bleibt.

Ein reales Beispiel: eine Dokumentationsseite mit sechzig Abschnitten, jeder mit mehreren Absätzen und teils Codebeispielen, profitiert enorm von content-visibility: auto auf Abschnittsebene. Vor der Optimierung dauert das initiale Rendering aller sechzig Abschnitte spürbar, insbesondere auf schwächeren Mobilgeräten. Nach der Optimierung rendert der Browser nur die ersten sichtbaren Abschnitte, der Rest wird erst beim Herunterscrollen berechnet. Die gemessene Verbesserung der Rendering-Zeit liegt bei solchen Seiten häufig im Bereich von fünfzig bis neunzig Prozent, abhängig von der Gesamtzahl und Komplexität der Abschnitte.


/* Documentation page: apply content-visibility per section,
   not to the wrapping container */
.doc-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 600px;
}

/* Mixed feed: different estimated heights per card type
   reduces initial layout shift when the card first renders */
.card--text {
  content-visibility: auto;
  contain-intrinsic-size: auto 180px;
}

.card--image {
  content-visibility: auto;
  contain-intrinsic-size: auto 420px;
}

5. content-visibility vs. display: none vs. visibility: hidden

Alle drei Eigenschaften klingen ähnlich, unterscheiden sich aber fundamental in ihrer Wirkung. display: none entfernt ein Element vollständig aus dem Layout und dem Accessibility Tree, jeglicher interner Zustand geht verloren, ein Video pausiert, eine Formulareingabe wird beim erneuten Einblenden zurückgesetzt, falls sie nicht extern gespeichert wurde. visibility: hidden behält den Platz im Layout bei, macht das Element aber unsichtbar und nicht interagierbar, die Rendering-Kosten bleiben jedoch vollständig erhalten, es wird also keine Arbeit gespart.

content-visibility: hidden ist ein Mittelweg: der Inhalt wird nicht gerendert und beansprucht daher keine Layout- oder Paint-Ressourcen, aber der interne Zustand bleibt erhalten, weil der DOM-Knoten nicht entfernt wird. Für Tab-Panels, Akkordeons und Modals, bei denen mehrfaches Ein- und Ausblenden ohne Zustandsverlust wichtig ist, ist content-visibility: hidden daher oft die bessere Wahl als display: none, insbesondere wenn die verborgenen Panels selbst komplexen Inhalt mit eigenem State enthalten.

6. Scrollposition, Find-in-Page und Tastaturnavigation

Ein häufig übersehener Aspekt von content-visibility: auto betrifft die Browser-Suche mit Strg+F. Da nicht gerenderte Inhalte für den Browser unsichtbar sind, würde eine naive Suche Treffer in ausgeblendeten Bereichen übersehen. Moderne Browser lösen das über das beforematch-Event: sobald die native Suchfunktion einen Treffer in einem Bereich mit content-visibility: auto findet, feuert dieses Event, und der Bereich wird automatisch gerendert und in den Viewport gescrollt, noch bevor der Nutzer etwas davon bemerkt.

Für Tastaturnavigation und Sprungmarken via Anker-Links gilt Ähnliches: springt ein Nutzer per #abschnitt-42 direkt zu einem Anker innerhalb eines Bereichs mit content-visibility: auto, aktiviert der Browser automatisch das Rendering dieses Bereichs, damit die Sprungmarke tatsächlich erreichbar ist. Dieses Verhalten ist Teil der Spezifikation und funktioniert ohne zusätzliches JavaScript, was content-visibility deutlich robuster macht als handgestrickte Lazy-Rendering-Lösungen, die solche Randfälle oft nicht abdecken.

7. Messen: DevTools Rendering-Panel und Performance-Trace

Um den Effekt von content-visibility zu belegen, reicht ein subjektiver Eindruck nicht aus. Im Chrome DevTools Performance-Panel zeigt ein aufgezeichneter Trace vor der Optimierung typischerweise lange, zusammenhängende Balken für Recalculate Style und Layout direkt nach dem Seitenaufbau. Nach dem Hinzufügen von content-visibility: auto auf die relevanten Container schrumpfen diese Balken deutlich, weil nur noch die sichtbaren Elemente berechnet werden. Zusätzlich lässt sich über die Rendering-Tab-Option "Layout Shift Regions" prüfen, ob contain-intrinsic-size korrekt kalibriert ist, sichtbare Sprünge deuten auf eine zu ungenaue Höhenschätzung hin.

Für automatisierte Messungen eignet sich die Performance-API im Browser, insbesondere PerformanceObserver mit dem Eintragstyp long-animation-frame, um lange Rendering-Blöcke zu erkennen, sowie Lighthouse für aggregierte Metriken wie Largest Contentful Paint und Total Blocking Time. Bei Seiten mit content-visibility ist besonders auf den First Contentful Paint zu achten, da dieser durch das reduzierte initiale Rendering meist deutlich früher eintritt, während Largest Contentful Paint stabil bleibt, solange das sichtbare Hero-Element nicht selbst von der Optimierung betroffen ist.


// Measure rendering cost reduction from content-visibility
// using the Long Animation Frames API
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(`Long frame: ${entry.duration.toFixed(1)}ms`, entry);
  }
});
observer.observe({ type: "long-animation-frame", buffered: true });

// Detect layout shifts caused by inaccurate contain-intrinsic-size
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      console.log(`Layout shift value: ${entry.value}`);
    }
  }
}).observe({ type: "layout-shift", buffered: true });

8. Kombination mit Containment und Lazy Loading

content-visibility: auto impliziert automatisch contain: layout style paint für Elemente, deren Inhalt aktuell nicht gerendert wird. Das bedeutet, dass sich die Effekte dieses Artikels eng mit klassischer CSS-Containment überschneiden, aber content-visibility geht einen Schritt weiter, weil es zusätzlich zur Isolation auch das komplette Überspringen der Rendering-Arbeit erlaubt, nicht nur deren Eingrenzung. Für Komponenten, die immer sichtbar bleiben sollen, aber ihre Rendering-Kosten von der Umgebung isolieren müssen, bleibt reines contain ohne content-visibility die richtige Wahl.

Bei Bildern lässt sich content-visibility gut mit nativem loading="lazy" kombinieren: loading="lazy" verzögert das Netzwerk-Laden der Bilddatei, content-visibility: auto verzögert zusätzlich die Rendering-Arbeit des umgebenden Containers. Beide Mechanismen ergänzen sich, weil sie an unterschiedlichen Stellen der Pipeline ansetzen, Netzwerk versus Rendering, und gemeinsam die stärkste Wirkung für bildlastige, lange Seiten erzielen.

9. content-visibility im direkten Vergleich

Die folgende Tabelle stellt die verschiedenen Ansätze zum Verstecken oder Aufschieben von Rendering-Arbeit gegenüber, damit die Entscheidung im konkreten Projekt leichter fällt.

Ansatz Rendering gespart Zustand erhalten Empfehlung
display: none Ja Nein Nur bei echtem Entfernen aus dem Dokument
visibility: hidden Nein Ja Nur für reines Verstecken ohne Performance-Ziel
content-visibility: hidden Ja Ja Tabs, Akkordeons, Modals mit Zustand
content-visibility: auto Ja, automatisch Ja Lange Listen, Feeds, Dokumentationsseiten
Manuelles Virtual Scrolling Ja, inklusive DOM-Entfernung Teilweise Sehr große Datenmengen, hoher Implementierungsaufwand

Der wichtigste Unterschied in der Tabelle liegt zwischen content-visibility: auto und manuellem Virtual Scrolling: Virtual Scrolling entfernt Elemente komplett aus dem DOM und spart damit zusätzlich Speicher, erfordert aber deutlich mehr JavaScript-Logik und bricht mit Standard-Browser-Features wie Find-in-Page und Fragment-Navigation, wenn es nicht sorgfältig implementiert wird. content-visibility bietet einen Großteil des Performance-Gewinns bei einem Bruchteil der Komplexität, weil es eine native Browser-Funktion ist und keine eigene Scroll-Simulation benötigt.

Mironsoft

CSS-Performance, Rendering-Optimierung und moderne Web-Frontends

Lange Seiten, die trotzdem flüssig scrollen?

Wir analysieren eure langen Listen, Feeds und Dokumentationsseiten, identifizieren Rendering-Engpässe und implementieren content-visibility mit korrekt kalibrierter contain-intrinsic-size für messbar schnelleres Rendering.

Rendering-Audit

Performance-Trace-Analyse und Identifikation der teuersten Layout-Bereiche

Implementierung

content-visibility und contain-intrinsic-size sauber in bestehende Komponenten integrieren

Messung

Vorher-Nachher-Vergleiche mit Lighthouse und Core Web Vitals

10. Zusammenfassung

content-visibility ist eine der wirkungsvollsten CSS-Eigenschaften für lange Seiten, weil sie Rendering-Arbeit für nicht sichtbare Bereiche vollständig überspringt, statt sie nur zu verzögern. Der Wert auto aktiviert dieses Verhalten automatisch und reaktiviert das Rendering, sobald ein Bereich in die Nähe des Viewports kommt. contain-intrinsic-size ist dabei kein optionales Extra, sondern notwendig, um Layout-Sprünge zu vermeiden, weil der Browser sonst keine Größe für nicht gerenderte Elemente kennt.

Im Vergleich zu display: none und visibility: hidden bietet content-visibility: hidden die beste Kombination aus Zustandserhalt und Rendering-Ersparnis für Tabs und Akkordeons. Für lange Listen und Feeds ist content-visibility: auto die richtige Wahl, mit deutlich weniger Implementierungsaufwand als manuelles Virtual Scrolling, bei ähnlichem Performance-Gewinn für die meisten Anwendungsfälle. Wer die Wirkung belegen will, misst mit dem Chrome DevTools Performance-Panel und der Layout-Shift-API vor und nach der Umstellung.

content-visibility für lange Seiten: Das Wichtigste auf einen Blick

Kernprinzip

content-visibility: auto überspringt Layout und Paint für Bereiche außerhalb des Viewports, reaktiviert automatisch beim Annähern.

Pflicht-Ergänzung

contain-intrinsic-size: auto Xpx verhindert Layout-Sprünge und stabilisiert die Scrollbar-Höhe.

Zustandserhalt

content-visibility: hidden behält internen Zustand, im Gegensatz zu display: none.

Browser-Funktionen

Find-in-Page, Fragment-Anker und Tastaturnavigation funktionieren automatisch über das beforematch-Event.

11. FAQ: content-visibility für lange Seiten

1Was macht content-visibility genau?
Überspringt Layout, Style und Paint für nicht sichtbaren Inhalt. auto aktiviert das automatisch je nach Nähe zum Viewport.
2Warum contain-intrinsic-size zusätzlich?
Ohne Platzhaltergröße schrumpft das Element auf null Höhe, Scrollbar und Layout werden instabil.
3Funktioniert Strg+F trotzdem?
Ja, über das beforematch-Event wird der Bereich automatisch gerendert, sobald die Suche dort einen Treffer findet.
4Ist das dasselbe wie display: none?
Nein. display: none verwirft den Zustand, content-visibility: hidden spart Rendering und behält den Zustand.
5Ab wie vielen Elementen lohnt es sich?
Ab etwa hundert bis zweihundert gleichartigen Elementen ist der Effekt in Traces deutlich messbar.
6Kann es Layout-Verschiebungen verursachen?
Nur bei falscher Kalibrierung. Das Schlüsselwort auto merkt sich die reale letzte Größe und reduziert Sprünge stark.
7Auf jedes Kind-Element anwenden?
Nein, nur auf sinnvolle Container-Einheiten wie Karten oder Abschnitte, nicht auf jede Verschachtelungsebene.
8Unterschied zu Virtual Scrolling?
Virtual Scrolling entfernt DOM-Knoten und spart Speicher, braucht aber viel JS. content-visibility ist nativ und einfacher.
9Welche Browser unterstützen es?
Chrome und Edge seit Version 85, Firefox seit 125, Safari seit 18. Die Eigenschaft ist additiv und braucht meist kein Fallback.
10Wie messe ich den Effekt?
DevTools Performance-Panel vorher/nachher, PerformanceObserver für long-animation-frame und layout-shift, plus Lighthouse.