Virtuelles Scrollen für hochperformante Benutzeroberflächen
Rendern Sie 500.000 Zeilen in einem Browser und Ihre Benutzeroberfläche wird wahrscheinlich einfrieren, ruckeln oder abstürzen. Während moderne Browser große DOM-Bäume durchaus verarbeiten können, verschlechtert sich die Performance oft dramatisch, wenn die Anzahl der Knoten aufgrund von Layout-, Stilberechnungs- und Speicherkosten wächst. Virtuelles Scrollen löst dieses Problem, indem es nur das rendert, was der Benutzer tatsächlich sehen kann — und diese einzelne Einschränkung verändert alles daran, wie datenintensive Benutzeroberflächen performen.
Wichtigste Erkenntnisse
- Virtuelles Scrollen rendert nur die im Viewport sichtbaren Elemente (plus einen kleinen Puffer), wodurch die Anzahl der DOM-Knoten unabhängig von der Datensatzgröße konstant bleibt.
- Es funktioniert, indem sichtbare Indizes aus
scrollTopberechnet, diese Elemente gerendert und Padding-Elemente verwendet werden, um die vollständige scrollbare Höhe zu simulieren. - Feste Elementhöhen halten die Implementierung einfach. Dynamische Höhen erfordern Messwert-Caching und sorgfältige Scroll-Position-Korrektur.
- Browser-native Suche (Strg+F), Barrierefreiheit und Scroll-Position-Stabilität erfordern alle zusätzliche Aufmerksamkeit in virtualisierten Listen.
- Ausgereifte Bibliotheken existieren für React, Angular und Vue — eine Eigenentwicklung ist in der Produktion selten notwendig.
Was ist virtuelles Scrollen (und warum ist es nicht Infinite Scroll)?
Virtuelles Scrollen (auch List Virtualization oder Windowing genannt) rendert nur die aktuell im Viewport sichtbaren Elemente plus einen kleinen Puffer darüber und darunter. Während der Benutzer scrollt, werden Elemente, die den Viewport verlassen, aus dem DOM entfernt und neue an ihrer Stelle eingefügt. Der gesamte Datensatz gelangt niemals vollständig ins DOM.
Dies unterscheidet sich grundlegend von Infinite Scroll. Infinite Scroll hängt Elemente an das DOM an, während Sie scrollen — die Liste wächst kontinuierlich. Virtuelles Scrollen tauscht Elemente ein und aus und hält die Anzahl der DOM-Knoten unabhängig von der Datensatzgröße ungefähr konstant.
Der praktische Unterschied ist erheblich. Eine naiv gerenderte Liste mit 100.000 Elementen könnte über 100.000 DOM-Knoten im Speicher erzeugen. Eine virtualisierte Liste desselben Datensatzes könnte zu jedem gegebenen Zeitpunkt 50–80 Knoten enthalten.
Wie virtualisierte Listen konzeptionell funktionieren
Der Mechanismus basiert auf einigen einfachen Ideen, die zusammenwirken:
Das Viewport-Fenster. Sie geben dem Scroll-Container eine feste Höhe. Diese definiert, wie viele Elemente gleichzeitig sichtbar sind — nennen wir es visibleCount = Math.ceil(containerHeight / itemHeight).
Index-Berechnung. Während der Benutzer scrollt, lesen Sie scrollTop, um zu bestimmen, welches Element oben im sichtbaren Bereich liegt: startIndex = Math.floor(scrollTop / itemHeight). Der End-Index folgt: endIndex = startIndex + visibleCount.
Scroll-Position-Illusion. Wenn Sie nur 50 Elemente rendern, würde die Scrollleiste eine winzige Liste widerspiegeln. Um die vollständige Höhe zu simulieren, platzieren Sie ein leeres Padding-Element über den gerenderten Elementen (Höhe = startIndex × itemHeight) und ein weiteres darunter (Höhe = verbleibender Platz). Die Scrollleiste verhält sich, als ob der vollständige Datensatz vorhanden wäre.
Overscan (Puffer). Das Rendern nur der exakt sichtbaren Elemente verursacht einen störenden Pop-in-Effekt beim schnellen Scrollen. Overscan rendert einige zusätzliche Zeilen über und unter dem Viewport — typischerweise 5–10 Elemente, je nach Anwendungsfall — sodass Elemente bereits im DOM sind, bevor sie in die Sichtbarkeit gleiten.
Feste vs. dynamische Elementhöhen
Virtualisierung mit fester Höhe ist unkompliziert und zuverlässig. Jede Berechnung ist einfache Arithmetik.
Dynamische Höhen sind deutlich schwieriger. Sie müssen entweder jedes Element nach dem Rendern messen und diese Messungen cachen, oder Höhen im Voraus schätzen und sie nach der Messung korrigieren. Beide Ansätze erhöhen die Komplexität und können zu Scroll-Position-Instabilität führen, wenn sie nicht sorgfältig behandelt werden. Wenn Ihr Anwendungsfall es erlaubt, lohnt es sich, auf feste Höhen hinzuarbeiten.
Discover how at OpenReplay.com.
Reale Kompromisse, die zu erwarten sind
Virtuelles Scrollen ist nicht kostenlos. Einige Dinge funktionieren nicht mehr oder erfordern zusätzliche Arbeit:
- Browser-Textsuche (Strg+F) funktioniert nicht mehr zuverlässig, da der meiste Inhalt nicht im DOM ist. Sie müssen Ihre eigene Suche implementieren.
- Barrierefreiheit erfordert Aufmerksamkeit. Wenden Sie
role="list",role="feed"oderrole="grid"auf den Container an. Sie können Attribute wiearia-setsizeundaria-posinsetverwenden, damit assistive Technologien die vollständige Listengröße und die Position jedes Elements verstehen können. Pflegen Sie das Fokus-Management, damit die Tastaturnavigation nicht abbricht, wenn Elemente unmounten. Ein kleiner Overscan-Puffer hilft auch Screenreadern zu erkennen, dass mehr Inhalt existiert. - Scroll-Position-Stabilität wird schwierig, wenn Daten dynamisch aktualisiert werden — Elemente, die oberhalb der aktuellen Scroll-Position hinzugefügt oder entfernt werden, können störende Sprünge verursachen.
Ökosystem-Unterstützung über Frameworks hinweg
Sie müssen dies in der Produktion selten von Grund auf neu entwickeln. Ausgereifte Bibliotheken behandeln die Randfälle:
- React: TanStack Virtual (headless, flexibel) und react-window (leichtgewichtig, unterstützt feste und variable Größen mit zusätzlichem Setup)
- Angular: CDK Virtual Scroll ist im Angular Component Dev Kit integriert
- Vue: vue-virtual-scroller deckt die meisten gängigen Muster ab
Eine CSS-Alternative, die es wert ist, gekannt zu werden: content-visibility: auto lässt den Browser das Rendern von Offscreen-Inhalten ohne JavaScript überspringen. Es kann die Paint-Performance bei moderaten Listen verbessern, reduziert aber nicht die Anzahl der DOM-Knoten und ist kein Ersatz für vollständige Virtualisierung bei großen Datensätzen.
Wann es tatsächlich eingesetzt werden sollte
Virtuelles Scrollen erhöht die Komplexität. Es lohnt sich, wenn:
- Ihre Liste einige hundert Elemente überschreitet und die Scroll-Performance merklich beeinträchtigt ist
- Sie Tabellen, Log-Viewer, Feeds oder Spreadsheet-ähnliche Benutzeroberflächen erstellen
- Speichernutzung eine Einschränkung darstellt (mobile Geräte, lang laufende Sitzungen)
Für kurze Listen sind Paginierung oder einfaches Lazy Loading oft einfacher und ausreichend.
Fazit
Benutzer benötigen keine 100.000 DOM-Knoten — sie müssen sich anfühlen, als könnten sie durch 100.000 Elemente scrollen. Virtuelles Scrollen liefert dieses Gefühl zu einem Bruchteil der Rendering-Kosten. Indem nur der sichtbare Ausschnitt eines Datensatzes gerendert und Elemente ein- und ausgetauscht werden, während der Benutzer scrollt, halten Sie die Anzahl der DOM-Knoten niedrig, die Speichernutzung vorhersehbar und die Bildraten flüssig. Die Kompromisse — defekte Strg+F-Suche, Barrierefreiheitsüberlegungen, Scroll-Position-Management — sind real, aber gut verstanden, und das Bibliotheks-Ökosystem über React, Angular und Vue hinweg behandelt die meisten davon out of the box. Wenn Ihre Liste groß genug ist, um die Performance zu beeinträchtigen, ist Virtualisierung das effektivste verfügbare Werkzeug.
Häufig gestellte Fragen
Ja, aber es erfordert zusätzliche Sorgfalt. Die meisten Virtualisierungs-Bibliotheken gehen von einem einspaltigen Listen-Layout aus. Für Grid-basierte Layouts müssen Sie sichtbare Zeilen und Spalten zusammen berechnen und dabei Elemente pro Zeile berücksichtigen. TanStack Virtual unterstützt Grid-Virtualisierung nativ. Bei anderen Bibliotheken müssen Sie möglicherweise jede Zeile als einzelnes virtualisiertes Element behandeln, das mehrere Zellen enthält.
Suchmaschinen-Crawler scrollen typischerweise nicht durch Inhalte, sodass Elemente außerhalb des initialen Renderings nicht indexiert werden. Wenn SEO für Ihren Listeninhalt wichtig ist, erwägen Sie paginierte HTML-Ausgabe oder Crawler-freundliche Alternativen. Wenn Sie serverseitig Inhalte rendern, wenden Sie die Virtualisierung erst nach der Hydration auf dem Client an.
Dies bedeutet normalerweise, dass Ihr Overscan-Puffer zu klein ist oder Ihr Element-Rendering zu langsam ist. Erhöhen Sie die Overscan-Anzahl, sodass mehr Offscreen-Elemente vorgerendert werden. Überprüfen Sie auch, ob Ihre Listenelemente teure Layout-Neuberechnungen auslösen oder Bilder synchron laden. Die Vereinfachung von Element-Komponenten und die Verwendung von Platzhalter-Inhalten für Bilder können leere Frames erheblich reduzieren.
Ja. Speichern Sie vor der Navigation den aktuellen scrollTop-Wert und den entsprechenden startIndex in State oder Session Storage. Wenn der Benutzer zurückkehrt, stellen Sie die Position des Scroll-Containers auf den gespeicherten scrollTop-Wert wieder her. Die meisten Virtualisierungs-Bibliotheken stellen eine scrollToIndex- oder scrollToOffset-Methode bereit, die dies beim Remount unkompliziert umsetzbar macht.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.