scroll-timeline und view-timeline ohne JavaScript
Eine Fortschrittsleiste, die sich beim Scrollen füllt, oder ein Bild mit Parallax-Effekt, wurde bisher fast immer mit einem JavaScript-Scroll-Listener gebaut, der bei jedem Scroll-Event neu berechnet. Mit scroll-timeline und view-timeline übernimmt der Browser diese Berechnung nativ und synchron zum Compositor-Thread, ganz ohne Skript.
Inhaltsverzeichnis
- 1. Das Problem mit JavaScript-Scroll-Listenern für Animationen
- 2. scroll-timeline Grundlagen
- 3. Praxisbeispiel: Progress-Bar beim Scrollen
- 4. view-timeline Grundlagen für Element-Sichtbarkeit
- 5. Parallax-Effekte mit view-timeline
- 6. Die animation-range Eigenschaft im Detail
- 7. Progressive Enhancement mit @supports und Tailwind-Utility-Klassen
- 8. Browser-Support-Stand von Scroll-Driven Animations
- 9. Best Practices und Performance-Hinweise
- 10. Zusammenfassung
- 11. FAQ
1. Das Problem mit JavaScript-Scroll-Listenern für Animationen
Scroll-gebundene Effekte wie eine Lesefortschritts-Leiste, ein Parallax-Hintergrund oder ein Element, das beim Einscrollen langsam einblendet, wurden bislang fast ausschließlich mit einem scroll-Event-Listener in JavaScript umgesetzt, der bei jedem Scroll-Schritt die aktuelle Scroll-Position ausliest und daraus einen Stilwert berechnet. Dieses Vorgehen funktioniert, läuft aber im Haupt-Thread des Browsers, der auch für Layout-Berechnungen, Skript-Ausführung und viele andere Aufgaben zuständig ist, wodurch häufiges Scroll-Event-Feuern zu spürbarem Ruckeln führen kann, besonders auf leistungsschwächeren Geräten.
Selbst mit Optimierungstechniken wie Throttling, Debouncing oder der Nutzung von requestAnimationFrame bleibt das grundlegende Problem bestehen, dass die Animation über den Haupt-Thread läuft und damit von dessen Auslastung abhängig ist. Native CSS-Scroll-Animationen über scroll-timeline und view-timeline lösen dieses Problem, indem der Browser die Animation direkt an die Scroll-Position koppelt und im performanteren Compositor-Thread berechnet, unabhängig davon, was der Haupt-Thread gerade tut.
2. scroll-timeline Grundlagen
Die CSS-Eigenschaft scroll-timeline definiert eine benannte Zeitachse, deren Fortschritt nicht wie bei klassischen CSS-Animationen von der verstrichenen Zeit abhängt, sondern vom Scroll-Fortschritt eines bestimmten Scroll-Containers. Ein Element mit scroll-timeline-name: --page-scroll und scroll-timeline-axis: block auf dem scrollenden Container erzeugt eine Zeitachse, die von null Prozent am Anfang des scrollbaren Bereichs bis hundert Prozent am Ende reicht.
Eine mit dieser Zeitachse verknüpfte animation läuft dann nicht mehr über eine feste Dauer in Sekunden, sondern über den gesamten Scroll-Fortschritt des Containers, gesteuert über die Eigenschaft animation-timeline: --page-scroll. Das bedeutet, die klassische animation-duration spielt für scroll-gebundene Animationen praktisch keine Rolle mehr, weil die Fortschrittsberechnung vollständig vom Scroll-Zustand statt von der Zeit übernommen wird.
3. Praxisbeispiel: Progress-Bar beim Scrollen
Eine Lesefortschritts-Leiste am oberen Bildschirmrand, die anzeigt, wie weit ein Nutzer einen Artikel bereits gescrollt hat, ist einer der häufigsten Anwendungsfälle für scroll-timeline. Statt eines JavaScript-Listeners, der bei jedem Scroll-Event die Breite eines Balkens per style.width setzt, übernimmt eine reine CSS-Keyframe-Animation, die die Breite von null auf hundert Prozent transformiert und über scroll-timeline an die Scroll-Position des Dokuments gekoppelt ist, dieselbe Aufgabe.
Im folgenden Beispiel wird die Zeitachse auf dem Wurzelelement definiert und eine Progress-Bar mit einer einfachen Keyframe-Animation daran gekoppelt. Der entscheidende Unterschied zur JavaScript-Lösung ist, dass der Browser die Breitenberechnung bei jedem einzelnen Scroll-Frame übernimmt, ohne dass ein einziges Byte JavaScript dafür geladen werden muss.
:root {
scroll-timeline-name: --page-scroll;
scroll-timeline-axis: block;
}
.progress-bar {
transform-origin: left;
animation: fill-progress linear;
animation-timeline: --page-scroll;
}
@keyframes fill-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
4. view-timeline Grundlagen für Element-Sichtbarkeit
Während scroll-timeline den Fortschritt des gesamten Scroll-Containers abbildet, adressiert die verwandte Eigenschaft view-timeline einen anderen, sehr häufigen Anwendungsfall: eine Animation, die genau dann läuft, wenn ein bestimmtes Element den sichtbaren Bereich des Viewports durchquert. Ein Element mit view-timeline-name: --card-reveal erzeugt eine Zeitachse, deren Fortschritt sich danach richtet, wie weit dieses spezifische Element gerade im Viewport sichtbar ist, unabhängig davon, wie lang die gesamte Seite ist.
Diese Eigenschaft eignet sich hervorragend für klassische Reveal-Animationen, bei denen einzelne Karten oder Abschnitte beim Einscrollen sanft einblenden oder sich leicht verschieben, ein Effekt, der bisher fast ausschließlich mit einem IntersectionObserver in JavaScript umgesetzt wurde, der beim Erreichen eines Schwellenwerts eine CSS-Klasse hinzufügt. Mit view-timeline entfällt dieser JavaScript-Umweg vollständig, weil der Browser selbst erkennt, wann und wie weit ein Element sichtbar ist.
5. Parallax-Effekte mit view-timeline
Ein klassischer Parallax-Effekt, bei dem sich ein Hintergrundbild langsamer bewegt als der übrige Seiteninhalt, lässt sich mit view-timeline umsetzen, indem ein Bildelement über die gesamte Sichtbarkeitsdauer im Viewport eine leichte, kontinuierliche Transformation durchläuft, etwa eine vertikale Verschiebung von minus zehn zu plus zehn Prozent. Weil die Animation direkt an die tatsächliche Sichtbarkeit des Elements gekoppelt ist, bleibt der Effekt exakt synchron zum Scroll-Verhalten, ohne die typische leichte Verzögerung, die bei JavaScript-basierten Parallax-Bibliotheken durch die Event-Verarbeitung im Haupt-Thread entstehen kann.
Gerade bei Hero-Bereichen mit großformatigen Bildern lohnt sich diese Technik, weil sie ohne zusätzliche JavaScript-Bibliothek auskommt und dennoch ruckelfrei bleibt, selbst auf Geräten mit begrenzter Rechenleistung, weil die Berechnung im Compositor-Thread läuft und nicht mit anderer Skript-Ausführung um Rechenzeit konkurriert. Wichtig ist, die Transformationswerte moderat zu halten, weil zu starke Parallax-Verschiebungen bei manchen Nutzern Unwohlsein auslösen können, weshalb sich auch hier eine Media Query auf prefers-reduced-motion empfiehlt.
6. Die animation-range Eigenschaft im Detail
Die Eigenschaft animation-range legt fest, in welchem Ausschnitt der Zeitachse eine Animation tatsächlich abläuft, statt zwingend die komplette Zeitachse von null bis hundert Prozent zu nutzen. Bei view-timeline lassen sich dafür benannte Bereiche wie entry, contain und exit verwenden, die jeweils die Phase beschreiben, in der ein Element gerade in den Viewport eintritt, vollständig sichtbar ist oder ihn wieder verlässt.
Ein Wert wie animation-range: entry 0% cover 40% sorgt dafür, dass die Animation ausschließlich während der Eintrittsphase des Elements läuft und danach im finalen Zustand verharrt, was für Reveal-Effekte typischerweise gewünscht ist, weil ein Element nur einmal beim ersten Erscheinen einblenden soll und nicht erneut animieren soll, wenn es später wieder aus dem Viewport verschwindet und zurückscrollt. Diese Feinsteuerung macht animation-range zu einem der mächtigsten Werkzeuge für präzise choreografierte Scroll-Effekte.
7. Progressive Enhancement mit @supports und Tailwind-Utility-Klassen
Da Scroll-Driven Animations rein additiv auf bestehende CSS-Animationen aufsetzen, lässt sich der Einsatz sauber mit @supports (animation-timeline: view()) absichern, um scroll-gebundenes Verhalten nur dort zu aktivieren, wo der Browser es tatsächlich unterstützt, während nicht unterstützende Browser das Element einfach in seinem Ausgangszustand belassen oder eine einfache, zeitbasierte Fallback-Animation erhalten. In Tailwind-Projekten lässt sich diese Bedingung über eine kleine Custom-Utility-Klasse kapseln, die die scroll-timeline-Deklarationen bündelt und im Markup wie jede andere Utility-Klasse eingesetzt wird.
Diese Kombination aus nativer CSS-Funktion und Utility-Klassen-Struktur passt gut zum Tailwind-Ansatz, weil sich wiederkehrende Scroll-Animationsmuster, etwa ein Card-Reveal oder eine Progress-Bar, als kleine, wiederverwendbare Klassen definieren lassen, die anschließend im Markup genauso deklarativ eingebunden werden wie jede andere Tailwind-Klasse, statt für jede einzelne Komponente eine eigene, individuelle Scroll-Logik zu schreiben.
8. Browser-Support-Stand von Scroll-Driven Animations
Chrome und Edge unterstützen scroll-timeline und view-timeline bereits seit Version 115 auf Basis von Blink vollständig, während Firefox und Safari die Implementierung zum jetzigen Zeitpunkt noch nicht vollständig abgeschlossen haben, was diese Technik zu einer der am wenigsten browserübergreifend verfügbaren CSS-Funktionen aus diesem Artikel macht. Wer produktiv scroll-gebundene Animationen einsetzt, sollte deshalb aktuell noch stärker auf progressive Enhancement setzen als bei den anderen hier vorgestellten Features.
Ein bewährtes Muster ist, das Element ohne Unterstützung in einem sinnvollen, statischen Zustand zu belassen, etwa eine bereits vollständig sichtbare Karte statt einer unsichtbaren, die nie einblendet, weil ohne @supports-Absicherung im schlimmsten Fall ein Element dauerhaft transparent bliebe. Diese defensive Grundhaltung, kombiniert mit einer regelmäßigen Prüfung des aktuellen Support-Standes, macht Scroll-Driven Animations schon heute produktiv nutzbar, ohne Nutzer nicht unterstützter Browser zu benachteiligen.
9. Best Practices und Performance-Hinweise
Ein wichtiger Performance-Vorteil von Scroll-Driven Animations gegenüber JavaScript-Lösungen ist, dass die Berechnung im Compositor-Thread läuft und damit unabhängig von der Auslastung des Haupt-Threads bleibt, was insbesondere auf Seiten mit viel gleichzeitig laufendem JavaScript, etwa umfangreichen Produktseiten mit Alpine.js-Komponenten, einen spürbaren Unterschied macht. Voraussetzung dafür ist, dass ausschließlich Compositor-freundliche Eigenschaften wie transform und opacity animiert werden, während das Animieren von Layout-relevanten Eigenschaften wie width oder top auch bei Scroll-Driven Animations weiterhin Layout-Neuberechnungen auslöst.
Zusätzlich sollte die Anzahl gleichzeitig aktiver Scroll-Timelines auf einer Seite bewusst begrenzt bleiben, weil zu viele parallel laufende Reveal-Effekte, etwa in einer sehr langen Liste von Karten, die Seite optisch überladen wirken lassen können, selbst wenn die reine Rechenleistung dafür ausreichen würde. Wie bei @starting-style gilt auch hier, gezielt einzelne, bedeutsame Elemente zu animieren, statt jede Komponente auf der Seite mit einem eigenen Scroll-Effekt zu versehen, und stets eine prefers-reduced-motion-Abfrage für Nutzer mit Bewegungsempfindlichkeit einzuplanen.
| Eigenschaft | Bezugspunkt | Typischer Einsatz | Browser-Support |
|---|---|---|---|
| scroll-timeline | Scroll-Fortschritt eines Containers | Lesefortschritts-Leiste, Seitenprogress | Chrome/Edge seit v115, Firefox/Safari in Arbeit |
| view-timeline | Sichtbarkeit eines einzelnen Elements | Card-Reveal, Fade-in beim Einscrollen | Chrome/Edge seit v115, Firefox/Safari in Arbeit |
| animation-range | Ausschnitt der Zeitachse (entry/exit/contain) | Präzise Kontrolle über Start und Ende der Animation | An scroll-timeline/view-timeline gekoppelt |
| JavaScript scroll listener | Manuell berechnete Scroll-Position | Fallback für nicht unterstützte Browser | Universell, aber Haupt-Thread-gebunden |
Mironsoft
Tailwind-CSS-Architektur, Design-Systeme und Performance
Tailwind-Frontends, die trotz tausender Utility-Klassen wartbar bleiben?
Wir prüfen bestehende Tailwind-Projekte auf aufgeblähte Klassenlisten, inkonsistente Design-Tokens und ungenutzte CSS-Reste und bauen daraus ein Design-System, das sich sauber skaliert statt mit jeder Komponente unübersichtlicher zu werden.
Design-System-Review
Tokens, Spacing-Skala und Komponentenkonsistenz auf Wartbarkeit prüfen.
Performance-Optimierung
CSS-Bundle-Größe, Purge-Konfiguration und Ladezeiten systematisch reduzieren.
Component-Architektur
Wiederverwendbare, gut strukturierte Komponenten statt Klassenlisten-Wildwuchs aufbauen.
10. Zusammenfassung
Scroll-Driven Animations: Das Wichtigste auf einen Blick
scroll-timeline
Koppelt eine Animation an den Scroll-Fortschritt eines Containers, ideal für Progress-Bars.
view-timeline
Koppelt eine Animation an die Sichtbarkeit eines einzelnen Elements im Viewport.
animation-range
Steuert präzise, in welcher Phase (entry, contain, exit) die Animation läuft.
Browser-Support
Bislang vor allem Chromium-basiert, @supports-Absicherung für Firefox/Safari nötig.