CSS Scroll Snap: Karussells und Galerien ohne JavaScript-Bibliothek
AI generated
{ }
@
CSS · Layout · Interaktion · Barrierefreiheit
CSS Scroll Snap
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.

15 Min. Lesezeit scroll-snap-type · scroll-snap-align Karussell · Galerie · Storytelling

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.

11. FAQ: CSS Scroll Snap: Das Wichtigste auf einen Blick

1Ersetzt CSS Scroll Snap jede JavaScript-Karussell-Bibliothek?
Fuer die meisten Faelle ja. Nur bei unendlichem Looping ohne sichtbaren Sprung oder synchronisierten Multi-Karussells mit gemeinsamem Zustand bleibt eine JS-Bibliothek noetig.
2Was ist der Unterschied zwischen mandatory und proximity?
mandatory rastet nach jedem Scroll-Vorgang zwingend an der naechsten Snap-Position ein. proximity rastet nur ein, wenn die Position bereits nahe genug liegt, sonst bleibt der Scroll frei.
3Warum rastet mein Karussell trotz scroll-snap-type nicht ein?
Meist fehlt scroll-snap-align auf den Kindelementen. scroll-snap-type allein auf dem Container reicht nicht, die Snap-Punkte muessen auf jeder Karte einzeln definiert werden.
4Wie verhindere ich, dass ein Sticky-Header Karten verdeckt?
scroll-padding auf dem Container definiert einen Sicherheitsabstand zur Kante, genau wie scroll-margin-top das bei Anker-Sprungzielen unter einem Sticky-Header macht.
5Funktioniert Scroll Snap auf Touchgeraeten genauso wie auf Desktop?
Ja, Scroll Snap funktioniert nativ mit Touch-Gesten, Momentum-Scrolling und Maus- oder Trackpad-Scrollen gleichermassen, ohne separaten Code fuer jedes Eingabegeraet.
6Ist Scroll Snap fuer Tastaturnutzer zugaenglich?
Ja, sobald der Container mit tabindex fokussierbar ist, funktioniert Pfeiltasten-Navigation automatisch, was viele selbstgebaute JS-Karussells nicht bieten.
7Was passiert in Browsern ohne Scroll-Snap-Unterstuetzung?
Das Feature degradiert sanft: Der Container bleibt normal scrollbar, nur das Einrasten fehlt. Ein spezieller Fallback ist praktisch nie noetig.
8Sollte ich die Scrollleiste bei einem Karussell ausblenden?
Optisch ja, mit scrollbar-width: none und dem WebKit-Pendant. Die Funktionalitaet bleibt erhalten, weil Touch- und Tastatur-Scrollen unabhaengig von der sichtbaren Leiste funktionieren.
9Ist vertikales Scroll Snap fuer lange Textseiten geeignet?
Selten. Bei variabler Inhaltslaenge kann mandatory das Lesen erschweren, weil der Browser mitten im Lesefluss einzurasten versucht. proximity oder kein Snap ist dort meist besser.
10Muss ich prefers-reduced-motion bei Scroll Snap beruecksichtigen?
Ja. scroll-behavior: smooth sollte per Media Query auf auto zurueckgesetzt werden, damit Nutzer mit reduzierter Bewegungspraeferenz kein erzwungenes Animations-Scrollen bekommen.