Gesteuertes Scrollen mit CSS Scroll Snap

Durch das Deklarieren von Scroll-Snapping-Positionen lassen sich gut kontrollierte Scroll-Erlebnisse schaffen.

Mit der Funktion CSS Scroll Snap können Webentwickler gut kontrollierte Scrollvorgänge erstellen, indem sie Scroll-Snapping-Positionen deklarieren. Beispiele hierfür sind Artikel mit Seitenzahlen und Bilderkarusselle. CSS Scroll Snap bietet eine benutzerfreundliche und konsistente API zum Erstellen dieser beliebten UX-Muster.

Hintergrund

Scroll-Snapping

Scrollen ist eine beliebte und natürliche Art, mit Inhalten im Web zu interagieren. Sie ist die native Methode der Plattform, um Zugriff auf mehr Informationen zu ermöglichen, als gleichzeitig auf dem Bildschirm sichtbar sind. Das ist besonders wichtig auf mobilen Plattformen mit begrenztem Bildschirmplatz. Es ist also keine Überraschung, dass Webautoren Inhalte zunehmend lieber in scrollbaren flachen Listen als in tiefen Hierarchien organisieren.

Der Hauptnachteil des Scrollens ist die mangelnde Präzision. Selten wird ein Scrollvorgang an einem Absatz oder Satz ausgerichtet. Das ist noch ausgeprägter bei paginierten oder in Abschnitte unterteilten Inhalten mit klaren Grenzen, wenn das Scrollen in der Mitte der Seite oder des Bildes endet und diese teilweise sichtbar bleiben. Bei diesen Anwendungsfällen ist ein gut kontrolliertes Scrollen von Vorteil.

Webentwickler haben sich lange auf JavaScript-basierte Lösungen zur Steuerung des Scrollens verlassen, um dieses Problem zu beheben. JavaScript-basierte Lösungen bieten jedoch keine vollständige Lösung, da es an Scroll-Anpassungsprimitiven oder dem Zugriff auf zusammengesetztes Scrollen mangelt. CSS Scroll Snap ist eine schnelle, präzise und nutzerfreundliche Lösung, die in allen Browsern einheitlich funktioniert.

Mit CSS Scroll Snap können Webautoren jeden Scroll-Container mit Grenzen für Scrollvorgänge markieren, an denen der Vorgang beendet werden soll. Browser wählen dann je nach den Besonderheiten des Scrollvorgangs, dem Layout und der Sichtbarkeit des Scrollcontainers sowie den Details der Andockpositionen die am besten geeignete Endposition aus und animieren dann reibungslos dorthin. Zurück zu unserem vorherigen Beispiel: Wenn der Nutzer das Karussell durchscrollt hat, wird das sichtbare Bild an der richtigen Position angezeigt. Es sind keine Scrollanpassungen durch JavaScript erforderlich.

Beispiel für die Verwendung von CSS-Scroll-Snapping mit einem Bildkarussell.
Beispiel für die Verwendung von CSS-Scroll-Snapping mit einem Bilderkarussell. Hier sorgt das Scroll-Snapping dafür, dass am Ende des Scrollens die horizontale Mitte eines Bildes an der horizontalen Mitte des Scroll-Containers ausgerichtet wird.

CSS Scroll Snap

Beim Scroll-Snapping wird der Scroll-Offset eines Scroll-Containers angepasst, sodass er sich nach Abschluss des Scrollvorgangs an einer bevorzugten Snap-Position befindet.

Ein Scrollcontainer kann mit der Property scroll-snap-type für das Scroll-Snapping aktiviert werden. Dadurch wird dem Browser mitgeteilt, dass er diesen Scrollcontainer an den von seinen untergeordneten Elementen erzeugten Andockpositionen ausrichten soll. scroll-snap-type bestimmt die Achse, auf der gescrollt wird: x, y oder both, und die Strenge des Einrastens: mandatory, proximity. Dazu später mehr.

Eine Einrastposition kann durch Deklarieren einer gewünschten Ausrichtung für ein Element erstellt werden. Diese Position ist der Scroll-Offset, bei dem der nächstgelegene Scroll-Container des übergeordneten Elements und das Element entsprechend der angegebenen Achse ausgerichtet sind. Die folgenden Ausrichtungen sind auf jeder Achse möglich: start, end, center.

Eine start-Ausrichtung bedeutet, dass der Startrand des Scroll-Containers mit dem Startrand des Element-Snap-Bereichs übereinstimmen sollte. Entsprechend bedeuten die Ausrichtungen end und center, dass der Endrand oder die Mitte des Scroll-Containers mit dem Endrand oder der Mitte des Element-Snap-Bereichs ausgerichtet werden soll.

Beispiel für verschiedene Ausrichtungen auf der horizontalen Scrollachse.

Die folgenden Beispiele veranschaulichen die Verwendung dieser Konzepte.

Ein häufiger Anwendungsfall für das Scroll-Snapping ist ein Bilderkarussell. Wenn Sie beispielsweise ein horizontales Bild-Carousel erstellen möchten, das beim Scrollen an jedem Bild einrastet, können Sie für den Scroll-Container einen obligatorischen scroll-snap-type auf der horizontalen Achse festlegen. Legen Sie für jedes Bild scroll-snap-align: center fest, damit das Bild im Carousel zentriert wird.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gal>ler<y"
  img src>=&q<uot;cat.jpg">
  <img src="dog.jpg"
  img> <src=>&quot;another_cute_animal.jpg"
/div

Da die Andockpositionen einem Element zugeordnet sind, kann der Andockalgorithmus anhand des Elements und der Größe des Scrollcontainers entscheiden, wann und wie er andockt. Angenommen, ein Bild ist größer als das Karussell. Ein einfacher Snapping-Algorithmus kann verhindern, dass der Nutzer das Bild schwenkt, um es vollständig zu sehen. Die Spezifikation erfordert jedoch, dass Implementierungen diesen Fall erkennen und dem Nutzer erlauben, frei in diesem Bild zu scrollen und nur an den Rändern einzurasten.

Beispiel: Produktseite mit Verlauf

Ein weiterer häufiger Anwendungsfall für das Scroll-Snapping sind Seiten mit mehreren logischen Abschnitten, die vertikal gescrollt werden können, z. B. eine typische Produktseite. scroll-snap-type: y proximity; ist für solche Fälle besser geeignet. Es wird nicht unterbrochen, wenn ein Nutzer zur Mitte eines bestimmten Abschnitts scrollt. Wenn er jedoch nah genug an einen neuen Abschnitt scrollt, wird der Bildschirm automatisch zum Anfang des neuen Abschnitts verschoben.

So gehts:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Scroll-Padding und -Rand

Die Produktseite hat einen fixierten Header oben. Außerdem sollte ein Teil des oberen Bereichs sichtbar bleiben, wenn der Scroll-Container eingerastet ist, um Nutzern einen Hinweis auf die Inhalte darüber zu geben.

Das Attribut scroll-padding ist ein neues CSS-Attribut, mit dem der effektive sichtbare Bereich des Scroll-Containers oder Snapport angepasst werden kann. Dieser wird bei der Berechnung der Scroll-Snap-Ausrichtungen verwendet. Die Eigenschaft definiert einen Einzug für das Padding-Feld des Scroll-Containers. In unserem Beispiel wurde oben 15vh zusätzlicher Inset hinzugefügt. Dadurch wird der Browser angewiesen, eine niedrigere Position, 15vh unter dem oberen Rand des Scrollcontainers, als vertikalen Startrand für das Scroll-Snapping zu verwenden. Beim Andocken wird die Startkante des Andockzielelements an diese neue Position angepasst, sodass darüber Platz bleibt.

Mit der Eigenschaft scroll-margin wird der Betrag für den Versatz definiert, mit dem das effektive Feld des Snap-Ziels angepasst wird. Das funktioniert ähnlich wie scroll-padding im Snap-Scroll-Container.

Vielleicht ist Ihnen aufgefallen, dass diese beiden Properties das Wort „snap“ nicht enthalten. Das ist so gewollt, da sie das Feld für alle relevanten Scrollvorgänge ändern und nicht nur für das Scroll-Snapping. Chrome berücksichtigt sie beispielsweise bei der Berechnung der Seitengröße für Paging-Scrollvorgänge wie PageDown und PageUp sowie bei der Berechnung des Scrollbetrags für den Element.scrollIntoView()-Vorgang.

Interaktion mit anderen Scrolling-APIs

DOM Scrolling API

Das Einrasten beim Scrollen erfolgt nach allen Scrollvorgängen, auch denen, die durch ein Skript initiiert wurden. Wenn Sie APIs wie Element.scrollTo verwenden, berechnet der Browser die beabsichtigte Scrollposition des Vorgangs und wendet dann die entsprechende Snapping-Logik an, um die endgültige Position zu ermitteln. Daher ist es nicht erforderlich, dass das Nutzer-Script manuelle Berechnungen für das Einrasten durchführt.

Optimiertes Scrollen

Mit „Smooth Scrolling“ wird das Verhalten eines programmatischen Scrollvorgangs gesteuert, während mit „Scroll Snap“ das Ziel festgelegt wird. Da sie orthogonale Aspekte des Scrollens steuern, können sie zusammen verwendet werden und sich gegenseitig ergänzen.

Overscroll-Verhalten

Die Overscroll behavior API steuert, wie das Scrollen über mehrere Elemente hinweg verkettet wird. Sie wird nicht durch Scroll-Snapping beeinflusst.

Einschränkungen und Best Practices

Vermeiden Sie die Verwendung des obligatorischen Einrastens, wenn die Zielelemente weit voneinander entfernt sind. Dadurch kann es passieren, dass Inhalte zwischen den Einrastpositionen nicht mehr zugänglich sind.

In vielen Fällen kann Scroll-Snapping als Erweiterung hinzugefügt werden, ohne dass eine Funktionserkennung erforderlich ist. Verwenden Sie bei Bedarf @supports oder CSS.supports, um die Unterstützung für CSS Scroll Snap zu erkennen. Vermeiden Sie die Verwendung von scroll-snap-type, das auch in der eingestellten Spezifikation vorhanden ist.

Funktionserkennung in CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Feature-Erkennung in JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Gehen Sie nicht davon aus, dass programmatische Scroll-APIs wie Element.scrollTo immer am angeforderten Scroll-Offset enden. Durch Scroll-Snapping kann der Scroll-Offset angepasst werden, nachdem das programmgesteuerte Scrollen abgeschlossen ist. Das war auch schon vor Scroll-Snapping keine gute Annahme, da das Scrollen aus anderen Gründen unterbrochen werden kann. Das gilt aber insbesondere für Scroll-Snapping.

Zukünftige Funktionen

Das Scrollen war das Thema einer kürzlich durchgeführten Umfrage des Chrome-Teams. Die Umfrageergebnisse haben mehrere Bereiche aufgezeigt, in denen zusätzliche Maßnahmen erforderlich sind, um die Lücke zwischen Plugin-Bibliotheken und CSS zu schließen. Die bevorstehenden Arbeiten konzentrieren sich auf scroll-snap und umfassen Folgendes:

  1. API-Verfügbarkeit und ‑Kompatibilität in verschiedenen Browsern.
  2. Wir arbeiten an neuen CSS-APIs wie scroll-start.
  3. Arbeiten Sie an neuen JS-Ereignissen wie snapChanged().