CSS Scroll-Driven Animations ermöglichen es dir, Elemente basierend auf der Scroll-Position zu animieren, ganz ohne JavaScript. Mit animation-timeline: scroll() und animation-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.

Intersection Observer: Ein mächtiges Tool für effizientes Web-Design 🚀
Erfahre, wie der Intersection Observer funktioniert und warum CSS Scroll-Driven Animations ihn teilweise ersetzen können.

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.

Größenangaben in CSS: Freud und Leid eines Entwicklers
CSS-Einheiten wie vh, vw und co. spielen auch bei Scroll-Driven Animations eine Rolle.

🎯 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:

RangeBeschreibung
entryElement tritt in den Viewport ein
exitElement verlässt den Viewport
containElement ist vollständig sichtbar
coverVon 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.

CSS scroll-driven animations - CSS | MDN
The official MDN documentation for CSS Scroll-Driven Animations.
Animate elements on scroll with Scroll-driven animations
Google Chrome's comprehensive guide to scroll-driven animations in CSS.

⚡ 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.