Communitygithub.com

Niltra/web-scrollytelling

Implementiert kinematografische Scroll-Erlebnisse im Apple-Stil (fixierte Helden, Canvas-Framesequenzen, Video-Scrubbing, erzählte Kapitel) mit GSAP ScrollTrigger, ohne Scroll-Jacking und mit gemessener Leistung. Verwende es für animierte Helden, fixierte Abschnitte, horizontale Galerien oder jeden Effekt, bei dem die Webseite wie ein Video wirkt, das du mit dem Scrollen steuerst.

Was ist web-scrollytelling?

Diese Skill-Anleitung beschreibt die Architektur und Implementierung von hochwertigen, filmischen Scrollytelling-Erlebnissen, ähnlich denen von Apple. Sie basiert auf GSAP ScrollTrigger und stellt strenge, nicht verhandelbare Regeln auf: Ein einziger Pinned-Container mit genau einer Timeline, striktes Verbot von Scroll-Jacking, ein einziger Animations-Loop und Auslagerung von Text ins DOM über dem Canvas. Der Fokus liegt auf flüssigen 60fps selbst auf mobilen Geräten. Die Anleitung deckt zwei Haupttechniken ab: Framesequenzen (wie von Apple verwendet) und Video-Scrubbing. Für Sequenzen werden maximal 90-120 WebP-Frames empfohlen, die mit einem gleitenden Fenster geladen werden (nur ±6-10 Frames um die aktuelle Position) und über IntersectionObserver und requestIdleCallback vorab dekodiert werden. Das Canvas rendert nur auf 1,5-fachem devicePixelRatio. Alternativ kann bei `<video>`-Elementen die `currentTime` über ein einziges requestAnimationFrame gesteuert werden, mit kurzem GOP-Intervall für ruckelfreies Scrubbing. Die Struktur ist modular aufgebaut: Kapitel werden über Progress-Bereiche definiert (z.B. 10%, 35%) mit Ein-/Ausblendungen und abwechselnden Seiten für Rhythmus. Horizontale Galerien nutzen Pin + `x`-Verschiebung. Zur Performance-Messung werden nur `transform`, `opacity` und `filter` animiert, gezielt `will-change` gesetzt und mit requestAnimationFrame auf echten Mobilgeräten getestet. Der QA-Hinweis warnt, dass iOS-Speichercrashes nicht durch einfaches Fenster- Resizing reproduzierbar sind. Die Skill-Datenstruktur verwendet ein geordnetes Array von „Einstellungen“ (`{ Typ: 'frames' | 'overlay' | 'galerie', ... }`), die die gesamte

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Niltra/agent-skills-web/tree/HEAD/skills/web-scrollytelling

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Kinematografisches Scrollytelling

Basisarchitektur (nicht verhandelbar)

  • Ein einziger Pin, eine einzige Timeline. Der Hero (oder das Hauptkapitel) pinnt einen Container, der N Viewport-Höhen überdauert, und ein Fortschritt von 0→1 steuert alles. Wenn mehrere konkurrierende Scroll-Animationen existieren, handelt es sich um eine normale Website mit Effekten – das ist nicht das, was wir meinen.
  • Nie Scroll-Jacking. Der Benutzer steuert die Geschwindigkeit mit seinem nativen Scrollen; die Animation wird „gescrubbt“ (scrub: true). Es ist verboten, das Mausrad zu kapern oder das Scrollen zu übernehmen.
  • Ein einziger Animationsloop. Lenis in den GSAP-Ticker integriert (autoRaf: false) und ScrollTrigger synchronisiert; oder nativer Scroll mit Scrub. Zwei konkurrierende Loops sind die häufigste Ursache für Ruckeln und lassen sich nicht durch Optimieren von Assets beheben.
  • Text lebt im DOM, über dem Canvas positioniert, mit Ebenen pro Fortschritt. Niemals Text innerhalb des Canvas rendern.

Framesequenzen (Apple-ähnliche Technik)

  • Bevorzugte Quelle: echtes Video → Frames mit ffmpeg (fps=12..24, auf Bildschirmauflösung skaliert). Export als WebP q≈68-75 und durch Betrachten des Ergebnisses justieren, nicht nach Bauchgefühl.
  • Maximal ~90-120 Frames; auf Mobilgeräten die Hälfte oder eine 720p-Version ausliefern.
  • Laden mit gleitendem Fenster: ±6-10 Frames um den aktuellen herum behalten; niemals die gesamte Sequenz dekodieren (eine vollständige 1080p-Sequenz zerstört iOS Safari).
  • Vorladen mit IntersectionObserver (rootMargin ~800px), requestIdleCallback für Decode und fetchPriority="low" außer beim Hero.
  • Canvas mit devicePixelRatio auf 1,5 begrenzt und cover/contain berechnet; nur dekodierte Frames zeichnen; fehlt der exakte Frame, den nächstgelegenen bereits geladenen verwenden (niemals schwarz zeichnen).
  • Unveränderlicher Cache (Cache-Control: public, max-age=31536000, immutable) mit versioniertem Dateinamen.
  • Fallback bei prefers-reduced-motion und langsamer Verbindung: statisches Poster + normale Kapitel ohne Pin.
  • Einfachere Alternative, wenn keine Nachbearbeitung nötig ist: src eines <img>-Elements pro Frame austauschen (zuverlässig in allen Browsern, kein Canvas nötig).

Video-Scrubbing (falls <video> verwendet wird)

  • currentTime gesteuert durch Fortschritt in einem einzigen requestAnimationFrame, mit Glättung; Seeks zusammenfassen (Safari staut die Warteschlange).
  • Als Blob laden, damit es zu 100% seekbar ist; mit kurzem GOP kodieren (Keyframe alle paar Frames), sonst ruckelt das Scrubbing.
  • Niemals Autoplay: Das Scrollen steuert es.

Kapitel und Overlays

  • Beats definiert durch Fortschrittsbereiche (10%, 35%, 60%, 85%...), mit Ein-/Ausblendungen und abwechselnden Seiten für Rhythmus.
  • Jedes Kapitel behält seinen Text im DOM in korrekter semantischer Reihenfolge für SEO.
  • Horizontale Galerien: Abschnitt pinnen + x an Fortschritt gekoppelt; die Karten werden zur Mitte hin skaliert.

Leistung und Überprüfung

  • Nur transform, opacity und filter animieren; will-change gezielt setzen und nach Abschluss entfernen.
  • Frames mit requestAnimationFrame lokal und auf echtem Mobilgerät messen, wenn möglich; Ziel 60fps auf einem durchschnittlichen Laptop.
  • Headless-Aufnahmen können das Canvas schwarz lesen (Buffer nicht erhalten): Über DOM überprüfen (berechnete Styles, Elemente, über window.debug exponierter Zustand) und mit aktiviertem Reduced-Mode-Modus.
  • Bei 375/768/1280/1440 testen; das Resizing eines Desktop-Browsers reproduziert den iOS-Speichercrash nicht: Dies im QA-Bericht vermerken.

Empfohlene Datenstruktur

Ein geordnetes Array von „Einstellungen“: jede Einstellung ist { typ: 'frames' | 'overlay' | 'galerie', ... }. Die Reihenfolge des Films ändern = die Liste neu ordnen. Die Frames werden durch ein Muster referenziert (/seq/einstellung-01/0001.webp).

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Verwandte Skills