CSS Scroll Snap
Mit CSS Scroll Snap könnt ihr steuern, dass der Browser an bestimmten Stellen stoppt, wenn über sog. Snap Points hinweg gescrolled wird.
Mit Hilfe der Scroll Snap-Technik von CSS könnt ihr steuern, dass der Browser an bestimmten Stellen im Layout einrastet, wenn über diese Punkte hinweg gescrolled werden soll. CSS Scroll Snap kann somit die Usability und die User Experience erheblich verbessern – z. B. beim Gestalten von Bildergalerien oder OnePagern mit verschiedenen Sektionen. Viele Scrolling-Effekte, für die früher JavaScript eingesetzt wurde, können dank Scroll Snap heute mit CSS gelöst werden.
Grundkonzept CSS Scroll Snap
Die Scroll Snap-Technik von CSS arbeitet mit einem Container-Element und darin enthaltenen Kind-Elementen.
Das Container-Element definiert in welchem Bereich das Scrolling-Verhalten stattfinden soll, ob horizontal oder vertikal gescrolled wird und wie streng der Browser sich verhalten soll was das »Einrast-Verhalten« angeht. Dazu existieren folgende Eigenschaften:
scroll-snap-type
scroll-snap-stop
scroll-padding
sowie zahlreiche ausführliche Schreibweisen (Longhand Properties)
Die CSS-Eigenschaft scroll-snap-type
ist hierbei zentral. Alleine mit dieser Eigenschaft können viele Lösungen erreicht werden.
Die Kind-Elemente sind die Elemente die gescrolled werden. Sie erhalten u.a. Eigenschaften um zu steuern wo beim Scrollen gestoppt werden soll. Die verfügbaren Eigenschaften sind:
scroll-snap-align
scroll-margin
sowie zahlreiche ausführliche Schreibweisen (Longhand Properties)
Auch hier ist die Eigenschaft scroll-snap-align
von zentraler Bedeutung.
Beispiel: Vertikal Scrollen
Schauen wir uns ein einfaches Beispiel an um zu verstehen, wie Scroll Snap funktioniert.
Der folgende Code erzeugt einen OnePager mit abwechseln farbigen Sektionen, die immer die gesamte Größe des Browserfensters einnehmen.
<body>
<section></section>
<section></section>
<section></section>
<section></section>
</body>
Der <body>
stellt das Container-Element dar. Mit scroll-snap-type: y mandatory;
definieren wir, dass vertikal gescrolled wird und das die »Snap Points« verpflichtend eingehalten werden müssen.
Achtung: Wichtig ist, dass im Container-Element gescrollt wird. In unserem Beispiel muss das html
-Element daher ein overflow: hidden
erhalten und das Container-Element ein overflow: scroll
.
Die <section>
-Elemente werden gescrolled. Mit scroll-snap-align: start;
bestimmen wir, dass die Oberkante jeder <section>
die Stelle markiert, an der beim Scrollen gestoppt werden soll. In Kombination mit dem mandatory
-Wert von scroll-snap-type
führt das dazu, dass der Browser immer automatisch zur nächstgelegenen Sektion scrollt, wenn der Scroll-Vorgang beendet wird.
html {
overflow: hidden;
height: 100vh;
}
body {
margin: 0;
overflow: scroll;
height: 100vh;
scroll-snap-type: y mandatory; /* Vertikal Scrollen und Snap Points streng einhalten */
}
section {
height: 100vh;
scroll-snap-align: start; /* An der Oberkante jeder Sektion soll gestoppt werden */
}
section:nth-of-type(even) {
background: #8cb11c;
}
section:nth-of-type(odd) {
background: #147c85;
}
Wenn es möglich sein soll den Scrollvorgang auch auf halben Sektionen abzubrechen ohne, dass der Browser automatisch zum nächsten bzw. letzten Abschnitt navigiert, dann kann anstelle des mandatory
-Werts auch proximity
verwendet werden. In diesem Fall scrolled der Browser nur automatisch, wenn man sich in der Nähe der Oberkante befindet. Was »in der Nähe« konkret bedeutet ist den Browsern überlassen.
Beispiel: Horizontal Scrollen
Das folgende Beispiel zeigt eine horizontale Bildergalerie. Die Breite des Containers ist so gewählt, dass immer nur ein Bild vollständig sichtbar ist. Zu Beginn ist dies das 1. Bild ganz links. Dank scroll-snap-align: center;
richten sich die Bilder immer zentriert aus, sobald gescrolled wird.
<div class="gallery">
<img src="…">
<img src="…">
…
</div>
.gallery {
width: 650px;
display: flex;
margin: 2em auto;
padding: 0 1em;
background: #04191b;
overflow-y: hidden;
scroll-snap-type: x mandatory; /* Horizontal scrollen und Snap Points streng einhalten */
}
img {
margin: 2em 1em;
scroll-snap-align: center; /* Die Mitte eines Bildes ist der Snap Point */
}
Beispiel: Scroll Padding
Die für den Scroll-Container gedachte Eigenschaft scroll-snap-padding
kommt zum Einsatz, wenn ein Innenabstand zum Snap Point gesetzt werden soll.
Das folgende Beispiel erweitert den oben bereits beschriebenen OnePager um einen fixierten Header mit 60 Pixel Höhe. Da dieser Header immer im Vordergrund liegt, muss der scroll-snap-align
-Wert der einzelnen Sektionen von oben um 60 Pixel verschoben werden.
<body>
<header></header>
<section></section>
<section></section>
…
</body>
html {
overflow: hidden;
height: 100vh;
}
body {
overflow: scroll;
height: 100vh;
padding-top: 60px;
scroll-snap-type: y mandatory;
scroll-padding-top: 60px;
}
header {
height: 60px;
width: 100%;
background: #3a444a;
position: fixed;
top: 0;
}
section {
height: 100vh;
border-top: 2px solid white;
scroll-snap-align: start;
}
…
Beispiel: Scroll Margin
Das Gegenstück zur scroll-padding
-Eigenschaft des Containers stellt die scroll-margin
-Eigenschaft der Kind-Elemente dar.
Das folgende Beispiel arbeitet mit Sinnabschnitten die einen großen Abstand zueinander aufweisen und immer an der Oberkante einrasten sollen. Um den Abstand nach oben immer einzuhalten, wurde scroll-margin
genutzt.
body {
scroll-snap-type: y mandatory;
}
.item {
background: #a6bcc7;
height: 50vh;
width: 50vw;
margin: 50px auto;
scroll-snap-align: start;
scroll-margin-top: 50px;
}
CSS Scroll Snap-Eigenschaften im Detail
Die oben gezeigten Beispiele haben hoffentlich einen guten Eindruck über die Möglichkeiten von Scroll Snap vermittelt. Eine detaillierte Übersicht über alle verfügbaren Eigenschaften findet ihr u.a. bei Mozilla.
Browser Support
Den detaillierten Browser-Support für dieses Feature könnt ihr auf caniuse.com einsehen.
Selbst wenn ein Browser Scroll Snap nicht unterstützen sollte, stellt dies kein großes Problem dar, da die Technik dank Progressive Enhancement einfach eingesetzt werden kann, wenn der entsprechende Browser-Support vorhanden ist.
Hallo Jonas,
eine Mischung aus dem Scroll-Snapping und normalem Scrollen bei der ein oder anderen Section ist wahrscheinlich nicht möglich, oder?
Danke Dir!
LG
Stefan
Hallo Stefan, du kannst z.B. eine einzelne Sektion mit scroll-snap-align: none; ausschließen.
Hallo Jonas, vielen Dank für diesen Tipp. Das werde ich die Tage ausprobieren!
Danke. Gibt es eine elegante Lösung, die den horizontalen Scrollbalken ausblendet? Dann wärs ein sehr schlanker Slider. ;)
.element {
scrollbar-width: none;
}
.element::-webkit-scrollbar {
width: 0;
}
Die Beispiele funktionieren in meinen Versuchen nicht mit dem body Element. Wenn Ihr die snap-scroll-type Eigenschaft auf das html-Element anwendet klappt es. Hier im Prinzip das erste Beispiel.
https://codepen.io/kholja/pen/QWbVRdx
Nachtrag: Auf html klappt es wiederum nicht mit Safari. Die bessere Lösung dürfte daher sein, ein eigenes Elternelement zu nutzen. Ich habe das Codepen-Beispiel mal angepasst und es funktioniert nun auf FF, Chrome, Safari, Safari iOS. Andere Browser habe ich noch nicht getestet – vielleicht hat ja jemand Lust… :-)
Wir haben den Artikel noch einmal überarbeitet. Die Beispiele funktionieren nun alle in FF, Chrome und Safari.
Hi, funktioniert super und genau was ich gesucht habe! Leider habe ich aber ein Problem nach meinem letzten Snap-DIV den Rest der Seite zu scrollen?! Die Seite springt immer an das Ende, überspringt den restlichen Content. Hast Du eine Idee was ich vielleicht falsch gemacht habe? Danke für Deine Hilfe.
Hallo,
klappt das auch mit WordPress?
Ich hätte das sehr gern aber mein Theme (Enfold) gibt das leider nicht her.
Hallo Mandy,
die Technik ist in CSS geschrieben und hat mit WordPress nichts zu tun. Es ist also grundsätzlich kompatibel mit WordPress. Wenn du ein spezielles Theme im Einsatz hast kann es sein, dass dieses Theme die Kompatibilität stört. Das muss dann im Einzelfall nachgeschaut werden. Zu einzelnen Themes können wir keine Aussagen treffen, da wir nur maßgeschneiderte WordPress-Themes anbieten.
Sehr kool. Genau das was ich gesucht hab. Danke!
Hi,
funktioniert leider alles nicht im Firefox 66.0
???
In Safari und Chrome klappt es.
Danke, Gruß!
Firefox 66 unterstützt die Funktion noch nicht – nur unter der Flag.
Scrolle mich hier durch den gesamten Artikel und wundere mich, dass nichts der Beispiele funktioniert, bis ich am Ende diesen Kommentar lese.
Dass das alles in FF nicht funktioniert sollte man vielleicht direkt zu Anfang kommunizieren. FF hat in De immer noch den größten Marktanteil. Eine Funktion zu nutzen, die FF nicht beherrscht, macht in sofern keinen Sinn.
Wie im Abschnitt Browser-Support beschrieben, ist die Technologie nach dem Prinzip des Progressive Enhancement spezifiziert und entsprechend einzusetzen. Dass FF Scroll Snap nicht unterstützt, ist daher zweitrangig. Wenn das ein Problem für ein Projekt darstellt, sollte man nochmal genau hinterfragen ob das Projekt wirklich entsprechend der Philosophie des Web konzipiert ist. Es dürfte eigtl. kein Fehler entstehen.
Seltsam, laut https://caniuse.com/#search=scroll-snap sollte es auch mit dem aktuellem FF68 funktionuckeln – aber auch euer Beispiel will irgendwie nicht.
Jemand eine Idee woran das liegen könnte?
Also, wenn ich den Link aufrufe sehe ich „FireFox 68“ rot und auch Chrome erst seit Version 69 auf grün. Scroll-snap wird sicher mal eine tolle Funktion, aber derzeit nicht „mal eben“ nutzbar, da nicht überall unterstützt (insbesondere mobile).