CSS Scroll Snap: Neue Lösungen für Smartphones und Tablets

In diesem Artikel zeige ich dir, wie du die relativ neue CSS-Eigenschaft Scroll Snap dazu verwendest, um Inhalte horizontal oder vertikal zu scrollen, Elemente einzurasten und somit neue platzsparende Lösungen für Smartphones und Tablets entwickelst.

Wenn du viel mit dem Smartphone oder Tablet surfst, dann wird dir diese Technik bestimmt schon häufiger aufgefallen sein. Du scrollst durch eine Seite und auf einmal findest du einen horizontalen Scrollbereich, in dem mehrere Leistungen, Teammitglieder oder Angebote dargestellt werden.

So wie hier:

Gerade bei sehr langen Seiten kann es eine angenehme Abwechslung sein, horizontal durch einen Bereich zu scrollen. Früher hat man dafür auf Javascript-Slider setzen müssen, doch mittlerweile lässt sich dieser Effekt allein mit CSS umsetzen.

Diesen Effekt würde man auch mit einem einfachen overflow-x: scroll; hinbekommen. Der Vorteil von Scroll-Snap gegenüber overflow-x: scroll; ist – und daher kommt auch der Name – dass die Elemente auf der Bühne „einschnappen“. D.h. du scrollst das Element bis zu einem bestimmten Punkt und beim Loslassen wird es vom Browser selbstständig auf der Bühne positioniert.

Das HTML-Grundgerüst für Scroll-Snap

Für unser Contao Onepager Theme SIRIUS haben wir einen Bereich mit 4 Leistungen angelegt. Jede Karte zeigt eine Leistung und man sieht in der Desktop-Ansicht sehr gut, dass diese 4 Karten, würden wir sie auf dem Smartphone einfach untereinander darstellen, sehr viel Platz einnehmen.

Das HTML-Grundgerüst basiert auf einem Reihe Start- und End-Element inkl. Bildern in Contao und sieht wie folgt aus:

<div class="row ce_rowStart">
  <div class="ce_image block">
    <figure class="image_container float_above">
	<img src="files/demo/service-1.jpg" width="481" height="846" alt="" itemprop="image">
    </figure>
  </div>
  <div class="ce_image block">
    <figure class="image_container float_above">
	<img src="files/demo/service-2.jpg" width="481" height="846" alt="" itemprop="image">
    </figure>
  </div>
  <div class="ce_image block">
    <figure class="image_container float_above">
	<img src="files/demo/service-3.jpg" width="481" height="846" alt="" itemprop="image">
    </figure>
  </div>
  <div class="ce_image block">
    <figure class="image_container float_above">
	<img src="files/demo/service-4.jpg" width="481" height="846" alt="" itemprop="image">
    </figure>
  </div>
</div>

Wichtig ist, dass die Karten alle innerhalb des gleichen übergeordneten Containers stehen, im Beispiel <div class="row ce_rowStart">. Also selbst wenn ich 8 Elemente habe und diese auf dem Desktop aus 2 x 4 Karten bestehen, sollten diese innerhalb der gleichen Reihe stehen.

Das (S)CSS-Grundgerüst für Scroll-Snap

Um die Karten in der Desktop Ansicht darzustellen, kann ich diese per Flexbox anordnen. Das hat einerseits den Vorteil, dass alle Elemente die gleiche Höhe bekommen, andererseits kann ich mit einer Zeile sagen, dass die Elemente automatisch in eine neue Zeile umbrechen sollen – bzw. eben gerade nicht, wie für unsere Smartphone-Ansicht notwendig.

.row {
  display: flex;

  @media screen and (min-width: 768px) {
    flex-wrap: wrap;
  }
}

.card {
  @media screen and (min-width: 550px) {
    width: 50%;
  }
  
  @media screen and (min-width: 768px) {
    width: 25%;
  }
}

Wenn du noch nicht mit SCSS gearbeitet hast, dann schau dir doch mal unser E-Book Crashkurs Sass an.

Scroll-Snap im Einsatz

Nun möchte ich diese Darstellung für kleinere Bildschirme mithilfe von Scroll-Snap optimieren. Dafür gebe ich dem übergeordneten Container die Scroll-Snap-Eigenschaft. Außerdem wird ein overflow: scroll für die entsprechende Richtung benötigt:

.row {
  display: flex;

  scroll-snap-type: x mandatory; // x = horizontal, y = vertical
  overflow-x: scroll; // needed for scroll-snap behaviour, fallback if scroll-snap is not supported
  -webkit-overflow-scrolling: touch; // needed for iOS
	
  @media screen and (min-width: 768px) {
    flex-wrap: wrap;
  }
}

Das x gibt dabei an, dass die Scrollrichtung horizontal sein soll und das mandatory, dass sich an die Snap-Points gehalten werden soll.

Nun sorge ich dafür, dass meine Elemente nicht 100% Breite haben, sondern nur so breit sind, dass sich das nächste Element im Anschnitt befindet. 100% Breite ginge auch, aber durch das nächste Element im Anschnitt mache ich dem Nutzer eher deutlich, dass sich da rechts vom ersten Element noch weitere Elemente befinden könnten:

.card {
  width: 80%; // decrease element width
  flex-shrink: 0; // make sure elements does not get smaller than 80% screen-width
  scroll-snap-align: center;
  overflow: visible; // needed for Contao, as most Elements use the "block" class with overflow: hidden;
  
  @media screen and (min-width: 550px) {
    width: 50%;
  }
  
  @media screen and (min-width: 768px) {
    width: 25%;
  }
}

Diese Zeilen reichen bereits aus, damit sich die Elemente scrollen lassen und selbstständig auf der Bühne „einschnappen“.Eine Übersicht über weitere CSS-Eigenschaften von Scroll-Snap findest du u.a. in den MDN Web Docs oder bei CSS-Tricks. Hier probierst du am besten selbst einmal aus, was alles möglich ist, zum Beispiel mithilfe dieser kleinen Demo, die ich bei Codepen angelegt habe.

Noch ein paar Worte zur Browser-Unterstützung: Laut Can I use liegt aktuell die Browser-Unterstützung zwischen 82% und knapp 85%, je nachdem ob man die Desktop-Browser mit einrechnet oder nicht.

Für Browser die Scroll-Snap noch nicht unterstützen, haben wir immerhin ein Fallback mit dem oben erwähnten overflow-x: scroll;. Dadurch gehen dem Nutzer keine wesentlichen Informationen auf der Seite verloren.

Ein Beispiel, wie wir Scroll-Snap umgesetzt haben, findest du in unserem SIRIUS-Theme.