Ich hab das hier in CSS gebaut: https://github.com/ulrischa/vanilla-scroll-sky
Ich wollte eigentlich nur etwas Einfaches.
Eine Möglichkeit, auf einer Website solche Storytelling-Abschnitte zu bauen, bei denen ein großes Bild beim Scrollen stehen bleibt und ein Text darüberläuft. So etwas sieht man in Reportagen, Magazinen, Datenstorys oder auf hochwertigen Landingpages. Es wirkt aufwendig, ist dramaturgisch stark und hilft, Inhalte nicht nur linear herunterzuschreiben, sondern sie als kleine Szene erlebbar zu machen.
Was ich aber nicht wollte: eine riesige JavaScript-Library, ein Framework, ein Animationsmonster oder jedes Mal wieder dieselben CSS-Konstruktionen von vorne zusammensuchen.
Also entstand die Idee zu Vanilla Scroll Sky.
Eine kleine, wiederverwendbare CSS-Lösung für moderne Scrollytelling-Abschnitte. Ohne JavaScript. Ohne Web Component. Ohne Build-Prozess. Nur HTML, CSS-Klassen und CSS Custom Properties.
Die Grundidee war simpel:
Ein Abschnitt soll aus einem Bild und einer Textbox bestehen.
Beim Scrollen passiert Folgendes:
Technisch steckt dahinter vor allem:
position: sticky;
Das Bild wird innerhalb seines Abschnitts „festgehalten“. Der Text bleibt normaler Seiteninhalt und scrollt weiter. Dadurch entsteht der Eindruck, dass die Textbox über das Bild hinwegwandert.
Dazu kommt eine scrollbasierte Animation:
animation-timeline: view();
Damit läuft die Animation nicht nach Zeit, sondern abhängig davon, wie das Element in den sichtbaren Bereich scrollt. Genau dafür sind CSS Scroll-driven Animations gedacht: Animationen können an eine Scrollposition gekoppelt werden statt an eine normale Zeitachse.
Das war der Kern.
Aber der Kern allein ist noch keine wiederverwendbare Lösung.
Eine Web Component lag nahe.
Man hätte dann so etwas schreiben können:
<scroll-story
reveal-from="left"
caption-motion="right-to-center"
>
<img slot="image" src="image.jpg" alt="">
<div slot="caption">
<h2>Überschrift</h2>
<p>Text über dem Bild.</p>
</div>
</scroll-story>
Das ist elegant. Die Nutzung ist angenehm. Die interne Struktur ist gekapselt. Shadow DOM verhindert Style-Lecks. Mehrere Instanzen können unterschiedliche Werte bekommen. Für eine saubere Komponenten-API ist das attraktiv.
Aber dann kam der entscheidende Haken:
Ohne JavaScript passiert bei einer Web Component gar nichts.
Nicht nur die Animation fehlt. Das Custom Element wird ohne JavaScript nicht initialisiert. Shadow DOM wird nicht aufgebaut. Slots werden nicht verarbeitet. Die interne Struktur existiert nicht.
Wenn JavaScript nicht geladen wird, steht auf der Seite nur ein unbekanntes HTML-Element mit Inhalt. Das ist für progressive enhancement nicht ideal, wenn das Ziel ausdrücklich eine möglichst einfache, robuste CSS-Lösung sein soll.
Also war klar: Web Component ist technisch schön, aber nicht die richtige Grundidee für dieses Projekt.
Früher hätte man für so etwas fast automatisch JavaScript eingesetzt. Scrollposition messen, Klassen setzen, Animationen triggern, vielleicht GSAP oder eine Scrollytelling-Library nutzen.
Heute kann CSS mehr.
Für Vanilla Scroll Sky waren besonders vier moderne CSS-Funktionen wichtig.
Mit animation-timeline: view() kann eine Animation an die Sichtbarkeit eines Elements gekoppelt werden. Das Bild kann also beim Hineinscrollen einblenden, ohne dass JavaScript die Scrollposition beobachtet.
Beispiel:
.vss__image {
opacity: 0;
transform: translateY(4rem) scale(.96);
animation: vss-image-in linear both;
animation-timeline: view();
animation-range: entry 0% cover 35%;
}
Das Bild startet leicht versetzt und unsichtbar. Beim Scrollen wird es sichtbar und bewegt sich in seine Endposition.
@scopeEin Problem bei normalen CSS-Komponenten ist: Styles können aus Versehen zu viel treffen.
Mit @scope lassen sich Selektoren auf einen bestimmten DOM-Teilbaum begrenzen. Man kann also sagen: Diese Regeln gelten nur innerhalb von .vss. Das ist keine Shadow-DOM-Kapselung, aber es reduziert Style-Lecks deutlich. MDN beschreibt @scope genau als Möglichkeit, Elemente in bestimmten DOM-Teilbäumen gezielt anzusprechen, ohne extrem spezifische Selektoren schreiben zu müssen.
@scope (.vss) {
:scope {
...
}
.vss__image {
...
}
.vss__caption {
...
}
}
@layer@layer hilft, CSS in kontrollierte Kaskadenschichten zu sortieren. Damit kann die Utility in einer eigenen Schicht liegen und sauber mit bestehendem Seiten-CSS zusammenspielen. @layer ist dafür gedacht, Cascade Layers zu deklarieren und deren Priorität zu steuern.
@layer vanilla-scroll-sky {
...
}
Das macht die Integration in größere Projekte kontrollierbarer.
Bei einer Scrollytelling-Utility sollte sich die Komponente nicht nur am Viewport orientieren. Sie sollte sich auch an ihrer eigenen Breite anpassen können. Genau dafür sind Container Queries gedacht: Styles können anhand der Größe eines Containers angewendet werden, nicht nur anhand der Viewportgröße.
:scope {
container: vss / inline-size;
}
@container vss (max-width: 44rem) {
.vss__caption {
margin-inline: 1rem;
}
}
Damit kann die Caption auf schmaleren Einbettungen anders reagieren, ohne dass die ganze Seite betroffen ist.
Vanilla Scroll Sky ist eine kleine CSS-Utility für Scrollytelling-Abschnitte.
Sie macht aus normalem HTML eine Scroll-Szene:
<section class="vss vss--image-left vss--caption-right-center">
<div class="vss__image">
<img src="image.jpg" alt="Beschreibung des Bildes">
</div>
<div class="vss__caption">
<h2>Eine Szene entsteht</h2>
<p>Dieser Text läuft über das sticky Bild.</p>
</div>
</section>
Das Prinzip ist bewusst einfach:
.vss ist der Story-Abschnitt..vss__image ist die sticky Bildbühne..vss__caption ist die Textbox, die darüberläuft.Vanilla Scroll Sky kann mehrere Dinge, ohne JavaScript zu benötigen.
Das Bild kann aus verschiedenen Richtungen erscheinen:
<section class="vss vss--image-left">
Mögliche Klassen:
vss--image-left
vss--image-right
vss--image-top
vss--image-bottom
vss--image-none
Damit lässt sich steuern, ob das Bild von links, rechts, oben, unten oder ohne Richtungsbewegung erscheint.
Das Bild bleibt während des Scrollens im Viewport stehen:
.vss__image {
position: sticky;
top: var(--vss-image-stick-top);
}
Wenn die Seite einen sticky Header hat, setzt man zum Beispiel:
<section
class="vss vss--image-left"
style="--vss-image-stick-top: 4.5rem;"
>
Die Caption ist normaler HTML-Inhalt. Sie scrollt weiter, während das Bild steht.
<div class="vss__caption">
<h2>Überschrift</h2>
<p>Text über dem Bild.</p>
</div>
Optional kann die Caption seitlich in die Szene laufen:
<section class="vss vss--caption-left-center">
Mögliche Klassen:
vss--caption-left-center
vss--caption-right-center
vss--caption-left-right
vss--caption-right-left
Die Varianten left-center und right-center sind eher lesbar. Die Varianten left-right und right-left sind stärker als Effekt und eignen sich besser für kurze Texte.
Jeder Abschnitt kann eigene Werte bekommen:
<section
class="vss vss--image-bottom vss--caption-left-center"
style="
--vss-image-stick-top: 4.5rem;
--vss-image-height: 62svh;
--vss-scene-duration: 220svh;
--vss-caption-delay: 36svh;
--vss-caption-motion-distance: 80vw;
"
>
Das ist der wichtigste Punkt: Man muss die CSS-Mechanik nicht immer wieder neu schreiben. Man setzt nur Klassen und Variablen.
--vss-scene-duration: 220svh;
Steuert, wie lange die Scroll-Szene insgesamt dauert.
--vss-image-height: 66svh;
Steuert die Höhe der Bildbühne.
--vss-image-stick-top: 4.5rem;
Steuert, wo das Bild im Viewport kleben bleibt.
--vss-caption-delay: 40svh;
Steuert, wann die Caption über das Bild kommt.
--vss-caption-motion-distance: 80vw;
Steuert, wie stark die Caption von links oder rechts bewegt wird.
--vss-image-start-offset: 4rem;
Für einen starken Reveal von links kann man zum Beispiel setzen:
<section
class="vss vss--image-left"
style="--vss-image-start-offset: 100vw;"
>
Dann startet das Bild weit außerhalb der Endposition und fährt deutlich sichtbar in die Szene.
Vanilla Scroll Sky ist bewusst keine vollständige Scrollytelling-Plattform.
Es ist keine JavaScript-Library. Es misst keine Scrollposition. Es lädt keine Medien nach. Es synchronisiert keine komplexen Kapitel. Es erzeugt keine Timeline-Editoren. Es ist keine Alternative zu großen Storytelling-Systemen, wenn man sehr komplexe dramaturgische Abläufe braucht.
Es ist auch keine echte Shadow-DOM-Komponente. @scope begrenzt die Utility-Selektoren, aber der Inhalt der Caption bleibt normales HTML und kann weiterhin Seitenstile erben. Das ist meistens gut, weil Typografie, Links und Inhaltsstile zur Website passen sollen. Es ist aber keine vollständige Abschirmung wie bei einer Web Component.
Und: Der animierte Teil basiert auf modernen CSS Scroll-driven Animations. Wenn ein Browser diese nicht unterstützt, bleibt der Inhalt lesbar, aber die Reveal-Animation fällt weg. Genau dafür gibt es einen Fallback im CSS.
<link rel="stylesheet" href="/assets/css/vanilla-scroll-sky.css">
Wenn die Website bereits mit Cascade Layers arbeitet, kann man die Datei in eine Komponenten-Schicht importieren:
@layer base, components, utilities;
@import url("/assets/css/vanilla-scroll-sky.css") layer(components);
<section
class="vss vss--image-left vss--caption-right-center"
style="
--vss-image-stick-top: 4.5rem;
--vss-image-height: 66svh;
--vss-scene-duration: 220svh;
--vss-caption-delay: 40svh;
--vss-caption-motion-distance: 80vw;
"
>
<div class="vss__image">
<img src="image.jpg" alt="Beschreibung des Bildes">
</div>
<div class="vss__caption">
<h2>Storytelling mit CSS</h2>
<p>Das Bild bleibt stehen, während dieser Text darüberläuft.</p>
</div>
</section>
Subtiler Caption-Effekt:
<section
class="vss vss--caption-right-center"
style="--vss-caption-motion-distance: 6rem;"
>
Starker Bild-Reveal:
<section
class="vss vss--image-left"
style="--vss-image-start-offset: 100vw;"
>
Bild nicht beschneiden, sondern vollständig zeigen:
<section
class="vss"
style="--vss-image-fit: contain;"
>
Wichtigen Bildbereich links oben halten:
<section
class="vss"
style="--vss-image-position: left top;"
>
Vanilla Scroll Sky ist weniger wegen des einzelnen Effekts interessant, sondern wegen des Prinzips.
Es zeigt, dass moderne CSS-Funktionen viele Aufgaben übernehmen können, für die man früher automatisch JavaScript eingesetzt hätte:
Das ist eine andere Art, über Frontend-Code nachzudenken. Nicht jede Interaktion braucht ein Script. Nicht jede wiederverwendbare UI braucht eine Web Component. Nicht jedes Storytelling braucht eine große Library.
Manchmal reicht eine kleine, gut strukturierte CSS-Utility.
Vanilla Scroll Sky entstand aus einem einfachen Wunsch:
Scrollytelling-Abschnitte mit Bild und Text sollen leicht wiederverwendbar sein, ohne jedes Mal die CSS-Mechanik neu zu bauen und ohne eine große JavaScript-Abhängigkeit einzuführen.
Der erste Weg über eine Web Component war technisch naheliegend, aber nicht passend zum Ziel. Denn ohne JavaScript wäre die Komponente nicht wirklich vorhanden gewesen.
Der bessere Weg war moderneres CSS:
@layer
@scope
@container
position: sticky
animation-timeline: view()
CSS Custom Properties
Das Ergebnis ist eine kleine Vanilla-CSS-Lösung für moderne Websites.
Als erster einen Kommentar schreiben.
Schreibe einen Kommentar