Karussells und Galerien nativ im Browser bauen, ganz ohne JavaScript-Bibliothek
Scroll Snap bringt das Verhalten klassischer Karussell-Bibliotheken direkt in den Browser: Der Nutzer scrollt frei, aber der Container rastet an definierten Positionen ein, sauber und ruckelfrei. Wer scroll-snap-type und scroll-snap-align richtig kombiniert, spart eine komplette JavaScript-Abhaengigkeit und bekommt dabei Touch-Gesten, Tastatursteuerung und Barrierefreiheit quasi geschenkt.
Inhaltsverzeichnis
- 1. Was CSS Scroll Snap ist und welches Problem es loest
- 2. scroll-snap-type: mandatory gegen proximity und die Scroll-Achse festlegen
- 3. scroll-snap-align: Einrastpunkte auf den Kindelementen definieren
- 4. scroll-padding und scroll-margin: Abstaende zum Snap-Punkt korrigieren
- 5. Rezept: horizontales Produktkarussell ohne Bibliothek
- 6. Vertikales Snap fuer Storytelling-Seiten und Vollbild-Sections
- 7. Barrierefreiheit: Tastatur, Touch und Scroll-Snap zusammen denken
- 8. Browser-Support und Fallback-Strategien
- 9. Wann CSS Scroll Snap reicht und wann eine Bibliothek noch sinnvoll ist
- 10. Zusammenfassung
- 11. FAQ
1. Was CSS Scroll Snap ist und welches Problem es loest
Scroll Snap ist ein CSS-Modul, das dem Browser mitteilt, an welchen Positionen ein Scroll-Container nach dem Loslassen der Maus, des Touchpads oder des Fingers einrasten soll. Statt ein Karussell mit JavaScript zu berechnen, Touch-Events abzufangen und Animationen manuell zu interpolieren, uebernimmt der Browser diese Arbeit selbst, direkt im nativen Rendering-Pfad und damit typischerweise deutlich fluessiger als jede JS-Loesung.
Vor Scroll Snap brauchte jedes Karussell auf einer Website eine externe Bibliothek mit eigenem CSS, eigener JavaScript-Logik und meist mehreren Kilobyte zusaetzlichem Code, nur um horizontales Scrollen mit Einrast-Punkten zu simulieren. Mit scroll-snap-type und scroll-snap-align reichen wenige CSS-Zeilen, um dasselbe Verhalten nativ zu erreichen, inklusive Tastatur-Navigation und Momentum-Scrolling auf Touchgeraeten, die eine JS-Loesung erst muehsam nachbauen muesste.
2. scroll-snap-type: mandatory gegen proximity und die Scroll-Achse festlegen
Die Eigenschaft scroll-snap-type gehoert auf den scrollenden Container und legt zwei Dinge fest: die Achse (x, y oder both) und die Strenge des Einrastens. Bei mandatory rastet der Container nach jedem Scroll-Vorgang zwingend an der naechsten Snap-Position ein, selbst wenn der Nutzer nur minimal gescrollt hat. Bei proximity rastet er nur ein, wenn er bereits nahe genug an einer Snap-Position liegt, sonst bleibt die Scroll-Position frei.
Fuer Produktkarussells ist mandatory fast immer die richtige Wahl, weil Nutzer erwarten, dass jede Wischgeste ein vollstaendiges Element zeigt und keine halb abgeschnittenen Karten stehen bleiben. Bei langen, frei scrollbaren Bildergalerien mit vielen Elementen ist proximity oft angenehmer, weil es dem Nutzer erlaubt, frei durchzuscrollen und nur am Ende sanft einzurasten, statt bei jedem kleinen Scroll-Impuls hart zu stoppen.
/* Horizontaler Container: mandatory Snap auf der X-Achse */
.karussell {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 1rem;
/* verhindert das Ruckeln beim programmatischen Scrollen */
scroll-behavior: smooth;
}
/* Lange Galerie: proximity ist weniger aufdringlich */
.galerie {
overflow-x: auto;
scroll-snap-type: x proximity;
}
3. scroll-snap-align: Einrastpunkte auf den Kindelementen definieren
Waehrend scroll-snap-type den Container steuert, legt scroll-snap-align auf jedem einzelnen Kindelement fest, an welcher Kante es einrasten soll: start, center oder end. Fuer ein Produktkarussell, bei dem jede Karte links buendig sichtbar sein soll, ist start die uebliche Wahl. Fuer ein Bild-Karussell, das jedes Bild mittig zentrieren soll, passt center besser, weil dann links und rechts gleich viel vom Nachbarelement sichtbar bleibt.
Wichtig ist, dass scroll-snap-align nicht am Container, sondern an jedem Kindelement selbst gesetzt wird. Vergisst man das, scrollt der Container zwar frei, rastet aber niemals ein, weil dem Browser die Information fehlt, wo genau die Snap-Punkte liegen. Diese Kombination aus Container- und Kind-Eigenschaft ist der haeufigste Stolperstein beim ersten Scroll-Snap-Setup.
<div class="karussell">
<div class="karte" style="scroll-snap-align: start;">Karte 1</div>
<div class="karte" style="scroll-snap-align: start;">Karte 2</div>
<div class="karte" style="scroll-snap-align: start;">Karte 3</div>
</div>
<style>
.karte { flex: 0 0 280px; scroll-snap-align: start; }
</style>
4. scroll-padding und scroll-margin: Abstaende zum Snap-Punkt korrigieren
Sitzt ueber dem Karussell ein Sticky-Header oder ein anderes fixiertes Element, rastet der Browser Karten trotzdem exakt an der Container-Kante ein, auch wenn diese optisch hinter dem Header verschwindet. scroll-padding auf dem Container loest das, indem es einen virtuellen Sicherheitsabstand zur Container-Kante definiert, genau wie scroll-margin-top das bei Anker-Sprungzielen unter einem Sticky-Header macht.
scroll-margin funktioniert umgekehrt auf dem Kindelement: Es verschiebt den individuellen Snap-Punkt einer einzelnen Karte, unabhaengig vom globalen Container-Padding. Das ist nuetzlich, wenn zum Beispiel nur die erste oder letzte Karte in der Reihe einen zusaetzlichen Randabstand braucht, etwa um links und rechts vom Bildschirmrand sichtbaren Freiraum als Scroll-Hinweis zu lassen.
.karussell {
scroll-padding-inline: 1rem; /* Abstand zur Container-Kante */
}
.karte:first-child {
scroll-margin-inline-start: 1rem; /* individueller Snap-Versatz */
}
5. Rezept: horizontales Produktkarussell ohne Bibliothek
Ein komplettes Produktkarussell braucht neben Snap nur noch overflow-x: auto, eine feste oder minimale Kartenbreite mit flex: 0 0 <breite> und ausreichend gap zwischen den Karten. Die Scrollleiste selbst kann optisch mit scrollbar-width: none plus dem WebKit-Pendant ausgeblendet werden, waehrend die Scroll-Funktionalitaet vollstaendig erhalten bleibt, weil Touch- und Tastatur-Scrollen unabhaengig von der sichtbaren Scrollleiste funktionieren.
Der entscheidende Vorteil gegenueber einer JS-Bibliothek zeigt sich beim ersten Interaktions-Frame: Ein natives Scroll-Snap-Karussell reagiert sofort auf die erste Touch-Beruehrung, weil der Browser den Scroll-Handler bereits eingebaut hat. Eine JS-Loesung muss dagegen erst geladen, geparst und initialisiert sein, bevor sie ueberhaupt auf Eingaben reagiert, was gerade auf mobilen Geraeten spuerbare Verzoegerung bedeutet.
.karussell {
display: flex;
overflow-x: auto;
gap: 1rem;
scroll-snap-type: x mandatory;
scrollbar-width: none;
}
.karussell::-webkit-scrollbar { display: none; }
.karte {
flex: 0 0 clamp(220px, 70vw, 320px);
scroll-snap-align: start;
}
6. Vertikales Snap fuer Storytelling-Seiten und Vollbild-Sections
Auf der Y-Achse eignet sich scroll-snap-type: y mandatory fuer Storytelling-Seiten, die von Section zu Section springen, aehnlich wie bei Praesentations-Folien. Jede Section bekommt height: 100vh und scroll-snap-align: start, sodass der Nutzer beim Scrollen immer eine vollstaendige Section sieht, nie einen halben Uebergang zwischen zwei Abschnitten.
Ein haeufiger Fehler bei vertikalem Snap ist, ihn auf lange Textseiten mit variabler Inhaltslaenge anzuwenden. Wenn eine Section laenger als die Bildschirmhoehe ist, kann mandatory das Lesen erschweren, weil der Browser versucht, an den definierten Punkten einzurasten, obwohl der Nutzer eigentlich noch innerhalb einer Section weiterlesen will. Fuer solche Faelle ist proximity oder ganz auf Snap verzichten die bessere Wahl.
7. Barrierefreiheit: Tastatur, Touch und Scroll-Snap zusammen denken
Anders als viele JS-Karussells unterstuetzt CSS Scroll Snap Tastaturnavigation automatisch, sobald der Container fokussierbar ist. Mit tabindex="0" auf dem Scroll-Container koennen Nutzer mit Pfeiltasten durch die Karten navigieren, und der Screenreader kuendigt den Container als scrollbaren Bereich an. Das ist ein Bereich, in dem viele selbstgebaute JS-Karussells scheitern, weil Tastatursteuerung dort oft komplett fehlt.
Wichtig bleibt trotzdem, dass jede Karte im Karussell weiterhin ihre eigene Fokus-Reihenfolge behaelt, etwa fuer Links oder Buttons innerhalb der Karte, und dass prefers-reduced-motion respektiert wird. Nutzer, die reduzierte Bewegung bevorzugen, sollten kein hartes scroll-behavior: smooth aufgezwungen bekommen, sondern eine Media-Query-Abfrage, die bei Bedarf auf sofortiges Springen umschaltet.
@media (prefers-reduced-motion: reduce) {
.karussell { scroll-behavior: auto; }
}
8. Browser-Support und Fallback-Strategien
Scroll Snap wird von allen aktuellen Browsern unterstuetzt, inklusive Safari, Chrome, Firefox und Edge, sowohl auf Desktop als auch mobil. Das Feature degradiert zudem sehr sanft: Ein Browser ohne Unterstuetzung ignoriert einfach die Snap-Eigenschaften und zeigt weiterhin einen normal scrollbaren Container, ohne dass die Grundfunktion des Karussells verloren geht. Ein spezieller Fallback-Code ist deshalb praktisch nie noetig.
Der einzige Punkt, den es zu pruefen lohnt, ist das Zusammenspiel mit position: sticky Elementen innerhalb des Snap-Containers, das in manchen Safari-Versionen historisch Eigenheiten zeigte. Bei komplexen Layouts mit verschachtelten Sticky- und Snap-Elementen lohnt sich ein manueller Test auf echten Geraeten, bevor eine solche Kombination produktiv ausgerollt wird.
9. Wann CSS Scroll Snap reicht und wann eine Bibliothek noch sinnvoll ist
Fuer die grosse Mehrheit der Karussell- und Galerie-Anwendungsfaelle im E-Commerce, von Produktbildern ueber Testimonial-Slider bis zu Kategorie-Kacheln, reicht CSS Scroll Snap vollstaendig aus und spart eine komplette Abhaengigkeit. Eine JS-Bibliothek bleibt nur dort sinnvoll, wo Funktionen gebraucht werden, die CSS grundsaetzlich nicht abbilden kann, etwa unendliches Looping ohne sichtbaren Sprung oder synchronisierte Multi-Karussells mit gemeinsamem Zustand.
| Eigenschaft | Wo gesetzt | Wichtigste Werte | Typischer Einsatz |
|---|---|---|---|
scroll-snap-type |
Container | x/y/both mandatory/proximity |
Achse und Strenge des Einrastens festlegen |
scroll-snap-align |
Kindelement | start/center/end |
Einrastpunkt jeder Karte definieren |
scroll-padding |
Container | Laengenwert | Sicherheitsabstand zu Sticky-Headern |
scroll-margin |
Kindelement | Laengenwert | Individuellen Snap-Versatz pro Karte setzen |
| JS-Bibliothek | extern | abhaengig vom Tool | Nur bei Looping oder synchronisierten Multi-Karussells |
Mironsoft
Modernes CSS, Layout-Architektur und Rendering-Performance
CSS, das wartbar bleibt statt mit jeder Änderung zu brechen?
Wir prüfen bestehende Stylesheets auf Spezifitäts-Chaos und Layout-Thrashing und bauen daraus eine CSS-Architektur mit Cascade Layers, Custom Properties und modernen Layout-Primitiven, die auch nach dem zehnten Feature noch verständlich ist.
CSS-Audit
Spezifität, Cascade-Konflikte und ungenutzte Selektoren systematisch aufdecken.
Architektur-Refactoring
Cascade Layers, Custom Properties und Design Tokens sauber einführen.
Performance-Tuning
Layout-Thrashing, teure Selektoren und Rendering-Engpässe gezielt beheben.
10. Zusammenfassung
CSS Scroll Snap: Das Wichtigste auf einen Blick
Grundprinzip
scroll-snap-type auf dem Container plus scroll-snap-align auf jedem Kind ersetzen JS-Karussell-Bibliotheken vollstaendig.
mandatory vs. proximity
mandatory fuer Produktkarussells mit vollstaendig sichtbaren Karten, proximity fuer lange, frei scrollbare Galerien.
Sticky-Header-Fix
scroll-padding auf dem Container und scroll-margin auf dem Kind korrigieren Snap-Punkte hinter fixierten Elementen.
Barrierefreiheit
Tastaturnavigation funktioniert automatisch mit tabindex, prefers-reduced-motion sollte scroll-behavior gezielt deaktivieren.