TL;DR: 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.
Mehr Artikel entdecken
CSS Grid: The Missing Counterpart to Flexbox 🧩
TL;DR: CSS Grid is the missing puzzle piece to your Flexbox knowledge. While Flexbox handles one-dimensional layouts, Grid gives you full control over rows AND columns simultaneously. This article covers everything from basics to subgrid – with practical examples you can use right away. You know Flexbox? Great. Time to
CSS Scroll-Driven Animations – No JavaScript Required 🎬
TL;DR: CSS Scroll-Driven Animations let you animate elements based on scroll position – entirely without JavaScript. With animation-timeline: scroll() and animation-timeline: view(), you can build progress bars, fade-ins, and parallax effects in pure CSS. Performant, elegant, and future-proof. 🤔 What Are Scroll-Driven Animations? Imagine scrolling through a website and elements move,
CSS Grid: Das fehlende Gegenstück zu Flexbox 🧩
TL;DR: CSS Grid ist das fehlende Puzzlestück zu Flexbox. Während Flexbox eindimensionale Layouts meistert, gibt dir Grid die volle Kontrolle über Zeilen UND Spalten gleichzeitig. In diesem Artikel lernst du alles von den Basics bis Subgrid – mit praktischen Beispielen, die du sofort einsetzen kannst. Du kennst Flexbox? Gut. Dann
View Transitions API: Smooth Page Transitions ohne Framework ✨
TL;DR: Die View Transitions API bringt butterweiche Seitenuebergaenge direkt in den Browser - ganz ohne Framework, ganz ohne JavaScript-Bibliothek. Einfach CSS und ein paar Zeilen JS. Hier erfaehrst du, wie das funktioniert und warum du es sofort ausprobieren solltest. 🤔 Was sind View Transitions ueberhaupt? Kennst du das? Du klickst
CSS :has() – Der Parent Selector, auf den alle gewartet haben 🎯
TL;DR: CSS :has() ist der lang ersehnte Parent Selector – du kannst jetzt endlich Eltern-Elemente basierend auf ihren Kindern stylen. Kein JavaScript mehr nötig, kein Workaround, einfach pures CSS. Und ja, es funktioniert in allen modernen Browsern. 🤔 Warum gab es nie einen Parent Selector? Wenn du schon länger CSS schreibst,
Container Queries in CSS: Das Ende von Media Queries? 📦
Container Queries machen Schluss mit dem Viewport-Chaos! 📦 Wie du deine Komponenten endlich wirklich responsive machst – und warum Media Queries trotzdem nicht tot sind.