Zum Inhalt springen
← Alle Artikel
Scrollytelling wie TikTok: eine Website, durch die man swipt statt scrollt
Design & UX

Scrollytelling wie TikTok: eine Website, durch die man swipt statt scrollt

Reguläres Scrollen langweilt. Wie Scrollytelling die TikTok-Erfahrung - ein Moment nach dem anderen, einrastend, interaktiv - auf eine Website überträgt: der richtige Stack, die Bausteine (Pin, Scrub, Snap) und die Bugs, an denen die meisten scheitern, allen voran das Snapping, das gegen das Smooth-Scrolling kämpft.

Eric MengeAutorEric MengeInhaber & Webentwickler bei EMIT Solution
Veröffentlicht
Lesezeitca. 11 Min.

Kurz gesagt

  • Scroll-Storytelling heißt: die Seite reagiert auf die Scroll-Position wie ein Film auf die Zeitleiste. Statt passiv vorbeizuscrollen, rastet man von Moment zu Moment ein - die UX, die TikTok groß gemacht hat, auf eine Website übertragen.
  • Für einfache Effekte reichen CSS scroll-snap und scroll-driven animations. Für echtes, kontrolliertes Storytelling (Pin, Scrub, choreografierte Übergänge) führt kaum ein Weg an Lenis für weiches Scrollen plus GSAP ScrollTrigger vorbei.
  • Der teuerste Bug: Smooth-Scrolling und Snapping kämpfen gegeneinander - die Seite rastet ein, das Ausschwingen schiebt zurück, sie rastet erneut. Der Fix ist ein geschwindigkeits- und richtungsabhängiges Snapping mit bewusster Totzone, nicht das Einrasten auf den nächstgelegenen Punkt.
  • Was auf dem Desktop begeistert, ruiniert auf dem Handy die Performance. Die pin-lastige Choreografie gehört hinter eine Desktop-Weiche; mobil braucht es eine schlanke Einblend-Variante. Und prefers-reduced-motion ist Pflicht, kein Extra.

Der Unterschied zwischen einer Website, an der man vorbeiscrollt, und einer, durch die man sich zieht, ist derselbe wie zwischen einem Prospekt und einem Film. TikTok hat einer ganzen Generation beigebracht, wie sich das anfühlen soll: ein Moment, dann der nächste, jeder rastet ein, man wischt weiter, es passiert etwas. Genau diese Erfahrung lässt sich auf eine Website übertragen - und ich habe eine ganze Seite darum herum gebaut.

Dieser Beitrag ist die Anleitung dazu: der Frame, der richtige Stack, die Bausteine - und vor allem die Bugs, an denen die meisten scheitern. Denn Scroll-Storytelling sieht in den fertigen Demos mühelos aus und ist in der Umsetzung ein Kampf gegen die Physik des Browsers.

Der Frame: von der Seite zum Feed

Reguläres Scrollen ist passiv. Der Inhalt liegt da, man bewegt sich daran vorbei, nichts reagiert. Ein Feed ist aktiv: Jeder Abschnitt ist ein abgeschlossener Moment, der die volle Aufmerksamkeit bekommt, bevor der nächste kommt. Das ist der ganze Trick von TikTok - nicht die Videos, sondern das Einrasten. Man ist nie zwischen zwei Inhalten, immer mittendrin in einem.

Auf eine Website übertragen heißt das: Abschnitte, die einrasten (Snap), Elemente, die festgehalten werden, während man scrollt (Pin), und Animationen, die nicht abgespielt, sondern an die Scroll-Position gekoppelt werden (Scrub). Zusammen ergeben sie das Gefühl, durch eine Geschichte zu ziehen statt eine Seite herunterzurollen.

Der Stack: wann CSS reicht und wann nicht

Der Reflex, sofort eine Bibliothek zu laden, ist falsch. Zwei Dinge kann modernes CSS allein:

/* Abschnitte rasten beim Scrollen ein */
.feed {
  scroll-snap-type: y mandatory;
  overflow-y: scroll;
  height: 100vh;
}
.feed > section {
  scroll-snap-align: start;
  height: 100vh;
}

Und für Effekte, die an den Scroll gekoppelt sind, gibt es scroll-driven animations - eine native CSS-Zeitleiste, die auf dem Scroll läuft statt auf der Uhr:

@keyframes fade-in { from { opacity: 0 } to { opacity: 1 } }
.reveal {
  animation: fade-in linear both;
  animation-timeline: view();   /* läuft, während das Element durch den Viewport zieht */
}

Das deckt einfache Fälle ab und kostet null JavaScript. Die Grenze ist schnell erreicht: Sobald man ein Element über einen langen Scrollweg festhalten (pinnen) und dabei mehrere Dinge präzise nacheinander animieren will - eine Karte fliegt zentral ein, wird groß, schrumpft an ihre Grid-Position, die nächste folgt - braucht man echte Kontrolle über die Timeline. In der Praxis heißt das GSAP ScrollTrigger, fast immer kombiniert mit einer Smooth-Scroll-Bibliothek wie Lenis, die das ruckelige native Scrollrad in eine weiche Bewegung verwandelt.

import Lenis from 'lenis';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);

const lenis = new Lenis({ duration: 1.4, smoothWheel: true });
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((t) => lenis.raf(t * 1000));
gsap.ticker.lagSmoothing(0);

Diese wenigen Zeilen sind das Fundament: Lenis übernimmt das Scrollen, ScrollTrigger hängt sich in dieselbe Zeitleiste. Ab hier ist jede Sektion eine Timeline.

Die drei Bausteine

Pin hält ein Element fest, während der Scroll weiterläuft - das ist die Bühne für einen Moment. Scrub koppelt eine Animation an die Scroll-Position: Man treibt sie vor und zurück, statt sie abzuspielen. Zusammen ergeben sie den Kern:

gsap.timeline({
  scrollTrigger: {
    trigger: '#about',
    start: 'top top',
    end: '+=120%',     // 1,2 Viewporthöhen Scrollweg für diesen Moment
    pin: true,         // Sektion bleibt stehen
    scrub: 0.6,        // Animation folgt dem Scroll (mit 0,6 s Nachlauf = weich)
    anticipatePin: 1,  // gegen das kurze Ruckeln beim Einpinnen
  },
})
  .to('.content', { xPercent: 0, opacity: 1, duration: 0.15 })
  .to({}, { duration: 0.65 })   // bewusste Pause: der Moment darf wirken
  .to('.content', { xPercent: -30, opacity: 0, duration: 0.20 });

Der leere Tween in der Mitte ist kein Fehler, sondern Dramaturgie: eine Haltephase, in der der Inhalt einfach steht und gelesen werden kann, bevor er wieder hinausgleitet. Snap schließlich lässt die Seite zwischen diesen Momenten einrasten. Und genau hier fängt der Ärger an.

Die Stolperfallen, an denen die meisten scheitern

1. Das Snapping kämpft gegen das Smooth-Scrolling

Der teuerste Bug, und er ist tückisch, weil beide Teile für sich funktionieren. Weiches Scrollen schwingt aus - nach dem Loslassen bewegt sich die Seite noch ein Stück weiter. Naives Snapping rastet auf den nächstgelegenen Punkt ein. Beide zusammen: Die Seite rastet ein, das Ausschwingen schiebt sie minimal weiter, das Snapping liest das als neue Bewegung und rastet erneut. Ergebnis ist ein Zittern oder ein Zurückspringen auf den vorherigen Abschnitt.

Die Lösung ist, nicht auf den nächstgelegenen Punkt zu snappen, sondern Geschwindigkeit und Richtung auszuwerten und eine Totzone einzubauen:

snap: {
  snapTo: (value, self) => {
    const v = self?.getVelocity() ?? 0;
    // Breite Totzone (±30): unterhalb wird das Ausschwingen ignoriert.
    if (v > 30) {            // scrollt nach unten -> nächster Punkt in Richtung
      return POINTS.find((p) => p > value + 0.01) ?? POINTS.at(-1);
    }
    if (v < -30) {          // scrollt nach oben -> vorheriger Punkt
      return [...POINTS].reverse().find((p) => p < value - 0.01) ?? POINTS[0];
    }
    // fast still -> nächstgelegener Punkt
    return POINTS.reduce((c, p) => Math.abs(p - value) < Math.abs(c - value) ? p : c);
  },
  duration: { min: 0.25, max: 0.5 },
}

Der Kern ist die Totzone von ±30: Unterhalb dieser Geschwindigkeit gilt die Bewegung als Ausschwing-Artefakt und wird ignoriert, nicht als Snap-Auslöser gewertet. Erst das hat bei mir das Zurückspringen beendet.

2. Transform-Reste verfälschen jede Messung

Wer Elemente per FLIP-Technik von ihrer Endposition zur Bildschirmmitte fliegen lässt, misst ihre Position mit getBoundingClientRect(). Der Fehler: Läuft die Animation ein zweites Mal (etwa nach einem Resize), sitzt auf dem Element noch der Transform des letzten Durchlaufs - und man misst eine verschobene, skalierte Position statt der echten. Die Karten fliegen dann an die falsche Stelle.

// VOR jeder Neuberechnung die Transform-Reste entfernen, sonst misst man Müll:
gsap.set(cards, { clearProps: 'transform' });
const rect = card.getBoundingClientRect();  // jetzt die echte Grid-Position

3. Snap-Punkte überleben kein Resize

Snap-Punkte werden aus konkreten Pixel-Positionen berechnet. Ändert sich das Layout - Fenster resized, Schrift geladen, Bild nachgeladen - stimmen sie nicht mehr, und die Seite rastet an absurden Stellen ein. Die Absicherung ist, sie bei jedem Refresh neu zu berechnen statt einmal beim Start:

ScrollTrigger.create({
  invalidateOnRefresh: true,
  onRefresh: () => computeSnapPoints(),  // Layout-abhängige Werte neu ermitteln
  snap: { /* ... */ },
});

4. Was auf dem Desktop begeistert, killt das Handy

Die harte Wahrheit: Die pin- und scrub-lastige Choreografie ist auf dem Smartphone eine Zumutung - für die Performance und für das Gefühl, weil sie mit dem nativen Touch-Scrolling ringt. Die saubere Lösung ist eine echte Weiche. Ab Desktop-Breite die volle Inszenierung, darunter nur schlanke Einblend-Animationen, die beim Hereinscrollen einmal abspielen:

const isDesktop = window.innerWidth >= 1024;
if (isDesktop) initFullChoreography();
else initSimpleReveals();   // gsap.from(el, { y: 40, opacity: 0, ... }) pro Sektion

Das ist kein fauler Kompromiss, sondern die richtige Entscheidung: Auf dem Handy will niemand eine festgehaltene Bühne, sondern flüssig durchscrollen.

Die Grenze: wann es begeistert und wann es nervt

Scroll-Storytelling ist ein Verstärker, kein Selbstzweck. Es lohnt sich, wenn es eine Geschichte gibt, die von der Führung profitiert - eine Selbstdarstellung, ein Produkt, eine Referenzstrecke. Es nervt, sobald es zwischen den Nutzer und eine simple Information tritt. Wer schnell eine Telefonnummer oder einen Preis sucht, will nicht durch eine Inszenierung gescrollt werden.

Und zwei Dinge sind Pflicht, keine Kür:

@media (prefers-reduced-motion: reduce) {
  /* Kein Pin, kein Scrub, keine Fly-ins - Inhalt einfach da und lesbar. */
}

Erstens: prefers-reduced-motion respektieren. Wer im System reduzierte Bewegung eingestellt hat - oft aus gutem Grund, von Reisekrankheit bis Konzentrationsstörung - bekommt die Inhalte ruhig und ohne Pin. Zweitens: Der Inhalt muss im HTML stehen und lesbar sein, auch ohne dass ein einziges Skript läuft. Die Animation ist die Kür über einer Seite, die auch ohne sie funktioniert - für Suchmaschinen, für Screenreader und für den Fall, dass das JavaScript scheitert.

Fazit

Die TikTok-Erfahrung auf einer Website ist kein Zauber, sondern drei Bausteine - Pin, Scrub, Snap - über einem weichen Scroll-Fundament. Der Unterschied zwischen einer Demo, die beeindruckt, und einer, die im echten Einsatz zittert, sind die Fallen dazwischen: das Snapping, das gegen das Ausschwingen kämpft, die Transform-Reste, die Messungen vergiften, die Snap-Punkte, die kein Resize überleben, und die Desktop-Choreografie, die man mobil bewusst abschaltet. Wer die kennt, baut kein Effekt-Feuerwerk, sondern eine Seite, durch die man sich gerne zieht - und an den richtigen Stellen kurz innehält.

Häufige Fragen

Was ist Scroll-Storytelling (Scrollytelling)?+

Eine Technik, bei der der Inhalt einer Website an die Scroll-Position gekoppelt ist: Beim Scrollen werden Elemente festgehalten, Animationen laufen synchron zur Scroll-Bewegung ab, und die Seite rastet von Abschnitt zu Abschnitt ein. Statt einer statischen Seite, an der man vorbeiscrollt, entsteht eine geführte Abfolge von Momenten - vergleichbar mit dem Durchswipen eines TikTok-Feeds.

Brauche ich JavaScript oder reicht CSS?+

Für einfache Fälle reicht CSS: scroll-snap-type für das Einrasten zwischen Abschnitten und scroll-driven animations (animation-timeline: view/scroll) für Effekte, die an den Scroll gekoppelt sind. Sobald man Elemente über einen längeren Scrollweg festhalten (pinnen) und mehrere Animationen präzise choreografieren will, braucht man JavaScript - in der Praxis GSAP ScrollTrigger, meist kombiniert mit einer Smooth-Scroll-Bibliothek wie Lenis.

Warum springt mein Scroll-Snapping zur falschen Stelle zurück?+

Fast immer, weil weiches Scrollen (Smooth Scroll) und Snapping gegeneinander arbeiten. Die Seite rastet auf einen Punkt ein, das Ausschwingen der Smooth-Scroll-Bibliothek bewegt sie minimal weiter, das Snapping interpretiert das als neue Bewegung und rastet erneut - es zittert oder springt zurück. Die Lösung ist, nicht auf den nächstgelegenen Punkt zu snappen, sondern die Scroll-Geschwindigkeit und -Richtung auszuwerten und eine Totzone einzubauen, unterhalb derer gar nicht gesnappt wird.

Funktioniert Scroll-Storytelling auf dem Smartphone?+

Nur mit einer eigenen, abgespeckten Variante. Die pin- und scrub-lastige Desktop-Choreografie kostet auf Mobilgeräten zu viel Rechenleistung und fühlt sich mit dem nativen Touch-Scrolling oft falsch an. Bewährt hat sich, ab einer bestimmten Breite (z. B. 1024 px) auf die volle Choreografie umzuschalten und darunter nur schlanke Einblend-Animationen zu zeigen.

Ist Scroll-Storytelling schlecht für Barrierefreiheit oder SEO?+

Nicht per se, aber es braucht Sorgfalt. prefers-reduced-motion muss respektiert werden - wer im System reduzierte Bewegung eingestellt hat, soll die Inhalte ohne die Animationen und ohne Pin bekommen. Der Inhalt selbst muss im HTML vorhanden und lesbar sein (nicht erst per Scroll erzeugt), dann ist auch SEO unkritisch. Wichtig ist außerdem, dass man immer weiterscrollen kann und nirgends festhängt.

Du willst mehr erfahren?

In einem kostenlosen Erstgespräch besprechen wir, wie du diese Themen für dein Unternehmen nutzen kannst. Kein Verkaufsgespräch, sondern eine ehrliche Einschätzung.

Kostenloses Erstgespräch vereinbaren