CSS Scroll-Driven Animations ermöglichen es dir, Elemente basierend auf der Scroll-Position zu animieren, ganz ohne JavaScript. Mitanimation-timeline: scroll()undanimation-timeline: view()kannst du Fortschrittsbalken, Fade-Ins und Parallax-Effekte rein deklarativ umsetzen. Performant, elegant und zukunftssicher.
🤔 Was sind Scroll-Driven Animations?
Stell dir vor, du scrollst durch eine Website und Elemente bewegen sich, blenden ein oder verändern sich, alles synchron zu deiner Scroll-Position. Klingt nach viel JavaScript? Nicht mehr.
CSS Scroll-Driven Animations sind eine neue CSS-Spezifikation, die es dir erlaubt, bestehende CSS-Animationen an den Scroll-Fortschritt zu koppeln. Statt einer zeitbasierten Animation läuft die Animation so schnell oder langsam, wie du scrollst. Kein requestAnimationFrame, kein IntersectionObserver, kein Event-Listener. Pures CSS.
Es gibt zwei Hauptkonzepte:
- Scroll Progress Timeline, Die Animation ist an den gesamten Scroll-Fortschritt eines Containers gebunden.
- View Progress Timeline, Die Animation startet und endet, wenn ein Element in den Viewport scrollt.
🕰️ Der alte Weg: JavaScript und IntersectionObserver
Bisher war der Standardweg für scroll-basierte Animationen ein Mix aus JavaScript und CSS. Du hast entweder einen scroll-Event-Listener verwendet oder den IntersectionObserver, um Klassen zu toggeln.
Ein typisches Beispiel sah so aus:
// Der alte Weg mit IntersectionObserver
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.animate-on-scroll').forEach(el => {
observer.observe(el);
});
/* Dazu die CSS-Klasse */
.animate-on-scroll {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s, transform 0.6s;
}
.animate-on-scroll.visible {
opacity: 1;
transform: translateY(0);
}
Das funktioniert. Aber es hat Nachteile: Du brauchst JavaScript, die Animation ist nicht wirklich an die Scroll-Position gekoppelt (sie triggert nur einmal), und bei vielen Elementen kann die Performance leiden.
🚀 Der neue Weg: Rein CSS mit animation-timeline
Jetzt kommt der spannende Teil. Mit CSS Scroll-Driven Animations brauchst du nur noch CSS. Der Schlüssel sind zwei neue Properties:
animation-timeline: scroll(), Bindet die Animation an den Scroll-Fortschritt.animation-timeline: view(), Bindet die Animation an die Sichtbarkeit eines Elements im Viewport.
scroll(), Die Scroll Progress Timeline
Mit scroll() sagst du dem Browser: "Hey, nutze den Scroll-Fortschritt als Zeitachse für diese Animation." Die Funktion akzeptiert zwei optionale Parameter:
animation-timeline: scroll(<scroller> <axis>);
/* Beispiele */
animation-timeline: scroll(); /* nächster scrollbarer Vorfahre, block axis */
animation-timeline: scroll(root); /* das Root-Element (viewport) */
animation-timeline: scroll(nearest); /* nächster scrollbarer Vorfahre */
animation-timeline: scroll(root inline); /* Root-Element, inline axis */
view(), Die View Progress Timeline
view() ist perfekt für Elemente, die animiert werden sollen, wenn sie in den sichtbaren Bereich scrollen. Denk an Fade-Ins, Slide-Ins oder Scale-Effekte.
animation-timeline: view();
animation-timeline: view(block); /* block axis (Standard) */
animation-timeline: view(inline); /* inline axis */
animation-timeline: view(block 50px); /* mit Inset */
🎯 Praxisbeispiel 1: Scroll-Fortschrittsbalken
Ein klassisches Beispiel: Ein Fortschrittsbalken oben auf der Seite, der anzeigt, wie weit du gescrollt hast. Früher brauchte das JavaScript. Jetzt? Drei CSS-Regeln.
.progress-bar {
position: fixed;
top: 0;
left: 0;
height: 4px;
background: linear-gradient(to right, #6366f1, #8b5cf6);
transform-origin: left;
/* Die Magie */
animation: grow-progress linear;
animation-timeline: scroll(root);
}
@keyframes grow-progress {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
Das war's. Kein JavaScript. Der Balken skaliert sich automatisch basierend auf deiner Scroll-Position. Smooth, performant und deklarativ.
🎯 Praxisbeispiel 2: Fade-In beim Scrollen
Elemente sollen einblenden, wenn sie in den Viewport scrollen? Mit view() ein Kinderspiel:
.fade-in {
animation: fade-in-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
Das Element startet unsichtbar und faded ein, sobald es in den Viewport scrollt. animation-range: entry 0% entry 100% bedeutet: Die Animation läuft während der gesamten "Entry"-Phase, also vom ersten Pixel bis das Element komplett sichtbar ist.
🎯 Praxisbeispiel 3: Parallax-Effekt
Parallax-Effekte waren bisher ein JavaScript-Albtraum. Jetzt geht's auch in CSS:
.parallax-element {
animation: parallax linear both;
animation-timeline: view();
}
@keyframes parallax {
from {
transform: translateY(-50px);
}
to {
transform: translateY(50px);
}
}
Das Element bewegt sich langsamer als der Rest der Seite. Subtil, elegant und ohne eine einzige Zeile JavaScript.
🎚️ animation-range: Präzise Kontrolle
Die wahre Power steckt in animation-range. Damit kontrollierst du exakt, wann die Animation starten und enden soll. Es gibt verschiedene benannte Bereiche:
| Range | Beschreibung |
|---|---|
entry | Element tritt in den Viewport ein |
exit | Element verlässt den Viewport |
contain | Element ist vollständig sichtbar |
cover | Von erstem bis letztem sichtbarem Pixel |
/* Nur während des Eintritts animieren */
animation-range: entry;
/* Nur die ersten 50% des Eintritts */
animation-range: entry 0% entry 50%;
/* Vom Eintritt bis zum Austritt */
animation-range: entry 0% exit 100%;
/* Nur wenn komplett sichtbar */
animation-range: contain;
/* Mit festen Werten */
animation-range: entry 20px entry 200px;
Du kannst damit unglaublich fein granulare Animationen bauen. Zum Beispiel ein Element, das nur während der ersten Hälfte des Eintritts einfaded und dann stehen bleibt.
⚙️ @keyframes im Scroll-Kontext
Ein wichtiger Punkt: Deine @keyframes funktionieren genauso wie immer. Der einzige Unterschied ist, dass die Zeitachse nicht in Sekunden gemessen wird, sondern in Scroll-Fortschritt (0% bis 100%).
@keyframes reveal {
0% {
opacity: 0;
transform: scale(0.8) rotate(-5deg);
filter: blur(10px);
}
50% {
opacity: 1;
filter: blur(0);
}
100% {
transform: scale(1) rotate(0deg);
}
}
.reveal-element {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry;
}
Das Schöne daran: Du kannst komplexe, mehrstufige Animationen definieren, die sich perfekt an die Scroll-Position anpassen. Alles bleibt deklarativ und vorhersagbar.
🌐 Browser-Support und Progressive Enhancement
Stand März 2026 ist der Support schon ziemlich gut. Chrome und Edge unterstützen Scroll-Driven Animations seit Version 115. Firefox hat sie seit Version 131 standardmäßig aktiviert. Safari unterstützt sie in den neueren Versionen.
Trotzdem solltest du Progressive Enhancement einsetzen. Die @supports-Regel ist dein bester Freund:
/* Basis-Styling ohne Animation */
.element {
opacity: 1;
transform: none;
}
/* Scroll-Animation nur wenn unterstützt */
@supports (animation-timeline: view()) {
.element {
animation: fade-in linear both;
animation-timeline: view();
animation-range: entry;
}
}
So funktioniert deine Seite überall, mit Animation wo möglich, ohne Animation als Fallback. Kein User sieht eine kaputte Seite.
⚡ Performance: CSS vs. JavaScript
Warum ist der CSS-Ansatz besser? Ganz einfach:
- Main Thread frei: CSS-Animationen laufen auf dem Compositor Thread. JavaScript-basierte Animationen blockieren den Main Thread.
- Kein Layout Thrashing: Der Browser optimiert CSS-Animationen automatisch. Bei JS musst du das selbst managen.
- Weniger Code: Kein JavaScript-Bundle, das geladen und geparst werden muss.
- Automatische Optimierung: Der Browser kann CSS-Animationen automatisch throttlen, wenn sie nicht sichtbar sind.
In meinen Tests war der Unterschied bei Seiten mit vielen animierten Elementen deutlich spürbar. Weniger Jank, smoothere Animationen, bessere Core Web Vitals.
💡 Fazit
CSS Scroll-Driven Animations sind ein Gamechanger. Was früher Dutzende Zeilen JavaScript brauchte, geht jetzt mit ein paar CSS-Properties. Die API ist intuitiv, die Performance ist hervorragend und der Browser-Support ist mittlerweile solide.
Mein Tipp: Fang mit dem Scroll-Fortschrittsbalken an. Das ist das einfachste Beispiel und du siehst sofort, wie mächtig das Ganze ist. Dann experimentiere mit view() und animation-range für Fade-Ins und Reveal-Effekte.
Die Zukunft der Web-Animationen ist deklarativ. Und sie ist jetzt.