Scroll-Driven Animations: scroll-timeline und view-timeline ohne JavaScript
AI generated
tw
Tailwind CSS · Scroll-Driven Animations · view-timeline · Performance
Scroll-Driven Animations
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.

16 Min. Lesezeit scroll-timeline · view-timeline Scroll-Driven Animations ohne JS

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.

11. FAQ: Scroll-Driven Animations: Das Wichtigste auf einen Blick

1Was ist der Unterschied zwischen scroll-timeline und view-timeline?
scroll-timeline koppelt eine Animation an den Scroll-Fortschritt eines gesamten Containers, während view-timeline eine Animation an die Sichtbarkeit eines einzelnen Elements im Viewport koppelt, unabhängig von der Gesamtlänge der Seite.
2Brauche ich für eine Scroll-Progress-Bar noch einen JavaScript Listener?
Nein, mit scroll-timeline und einer CSS Keyframe Animation lässt sich eine Progress Bar vollständig deklarativ umsetzen, ohne dass ein Scroll Event Listener die Breite per Skript setzen muss.
3Wofür wird die animation-range Eigenschaft benötigt?
Sie legt fest, in welchem Ausschnitt der Zeitachse eine Animation tatsächlich läuft, etwa nur während der Eintrittsphase eines Elements, statt zwingend die komplette Zeitachse von null bis hundert Prozent zu nutzen.
4Warum sind Scroll-Driven Animations performanter als JavaScript Lösungen?
Die Berechnung läuft im Compositor Thread des Browsers statt im Haupt Thread, wodurch die Animation unabhängig von der Auslastung durch Skript Ausführung und Layout Berechnungen bleibt.
5Welche Browser unterstützen scroll-timeline und view-timeline bereits?
Chrome und Edge unterstützen beide Eigenschaften vollständig seit Version 115, Firefox und Safari haben die Implementierung zum jetzigen Zeitpunkt noch nicht vollständig abgeschlossen.
6Wie kann ich Scroll-Driven Animations als progressive Enhancement einsetzen?
Mit einer @supports Abfrage auf animation-timeline: view() lässt sich scroll gebundenes Verhalten nur dort aktivieren, wo der Browser es unterstützt, während andere Browser das Element in einem sinnvollen statischen Zustand belassen.
7Eignet sich view-timeline für Parallax Effekte?
Ja, ein Bildelement kann über die gesamte Sichtbarkeitsdauer eine leichte, kontinuierliche Transformation durchlaufen, was einen exakt zum Scroll Verhalten synchronen Parallax Effekt ohne JavaScript ergibt.
8Welche CSS Eigenschaften sollte ich bei Scroll-Driven Animations animieren?
Am performantesten sind transform und opacity, weil sie vom Compositor Thread ohne Layout Neuberechnung verarbeitet werden, während Eigenschaften wie width oder top weiterhin teure Layout Neuberechnungen auslösen.
9Was passiert mit dem Element, wenn ein Browser Scroll-Driven Animations nicht unterstützt?
Ohne @supports Absicherung könnte ein Element dauerhaft im transparenten Ausgangszustand verharren, weshalb ein sinnvoller, sichtbarer Fallback Zustand explizit definiert werden sollte.
10Sollte ich prefers-reduced-motion bei Scroll-Driven Animations berücksichtigen?
Ja, wie bei jeder bewegungsbasierten Animation sollte eine Media Query auf prefers-reduced-motion die Effekte für Nutzer mit Bewegungsempfindlichkeit reduzieren oder vollständig deaktivieren.