Gesteuertes Scrollen mit CSS Scroll Snap

Erstellen Sie gut kontrollierte Scroll-Erlebnisse, indem Sie Scroll-Snap-Positionen deklarieren.

Mit der Funktion CSS Scroll Snap können Webentwickler durch Deklarieren von Scroll-Snap-Positionen ein gut kontrolliertes Scrollen ermöglichen. Seitenweise Artikel und Bilderkarussells sind zwei häufig verwendete Beispiele dafür. CSS Scroll Snap bietet eine nutzerfreundliche und einheitliche API zum Erstellen dieser beliebten UX-Muster.

Hintergrund

Argumente für Scroll Snap

Scrollen ist eine beliebte und natürliche Art, mit Inhalten im Web zu interagieren. Es ist die native Methode der Plattform, um Zugriff auf mehr Informationen zu bieten, als auf dem Bildschirm auf einmal sichtbar sind. Das ist besonders auf mobilen Plattformen mit begrenztem Bildschirmplatz wichtig. Es ist also nicht überraschend, dass Webautoren Inhalte immer häufiger in scrollbaren flachen Listen statt in tiefen Hierarchien organisieren.

Der größte Nachteil des Scrollens ist die mangelnde Präzision. Selten wird ein Scrollvorgang an einem Absatz oder Satz ausgerichtet. Dies ist noch ausgeprägter bei paginierten oder aufgeschlüsselten Inhalten mit sinnvollen Grenzen, wenn das Scrollen in der Mitte der Seite oder des Bildes endet und diese nur teilweise sichtbar sind. Diese Anwendungsfälle profitieren von einer gut kontrollierten Scrollfunktion.

Webentwickler haben sich lange Zeit auf JavaScript-basierte Lösungen verlassen, um das Scrollen zu steuern und dieses Problem zu beheben. JavaScript-basierte Lösungen bieten jedoch keine vollständige Lösung, da keine Primitiven zur Anpassung des Scrollens oder Zugriff auf zusammengesetztes Scrollen vorhanden sind. CSS Scroll Snap ist eine schnelle, zuverlässige 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 sie enden sollen. Browser wählen dann je nach den Besonderheiten des Scrollvorgangs, dem Layout und der Sichtbarkeit des Scrollcontainers sowie den Details der Einrastpositionen die am besten geeignete Endposition aus und animieren sie dann flüssig. Zurück zu unserem vorherigen Beispiel: Wenn der Nutzer das Scrollen im Karussell beendet, rastet das sichtbare Bild ein. Keine Scrollanpassungen durch JavaScript erforderlich.

Beispiel für die Verwendung von CSS Scroll Snap mit einem Bildkarussell.
Beispiel für die Verwendung von CSS Scroll Snap mit einem Bildkarussell. Hier sorgt Scroll Snap dafür, dass am Ende des Scrollvorgangs die horizontale Mitte eines Bildes an der horizontalen Mitte des Scrollcontainers ausgerichtet ist.

CSS Scroll Snap

Beim Scroll Snap wird der Scroll-Offset eines Scroll-Containers so angepasst, dass er sich nach Abschluss des Scrollvorgangs an einer bevorzugten Andockposition befindet.

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

Eine Einrastposition kann durch Deklarieren einer gewünschten Ausrichtung für ein Element erzeugt werden. Diese Position ist der Scroll-Offset, bei dem der nächstgelegene übergeordnete Scroll-Container und das Element wie für die angegebene Achse angegeben ausgerichtet sind. Die folgenden Ausrichtungen sind auf jeder Achse möglich: start, end, center.

Eine start-Ausrichtung bedeutet, dass die Startkante des Scroll-Containers mit der Startkante des Element-Andockbereichs bündig sein sollte. Ebenso bedeuten die Ausrichtungen end und center, dass die Endkante oder die Mitte des Scroll-Containers mit der Endkante oder der Mitte des Element-Andockbereichs bündig sein sollte.

Beispiel für verschiedene Ausrichtungen auf der horizontalen Scrollachse.

Die folgenden Beispiele veranschaulichen, wie diese Konzepte verwendet werden.

Ein häufiger Anwendungsfall für Scroll Snap ist ein Bilderkarussell. Wenn Sie beispielsweise ein horizontales Bildkarussell erstellen möchten, das beim Scrollen zu jedem Bild springt, können Sie für den Scrollcontainer ein obligatorisches scroll-snap-type auf der horizontalen Achse festlegen. Setzen Sie jedes Bild auf scroll-snap-align: center, damit das Bild beim Springen im Karussell zentriert wird.

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

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

Da die Einrastpositionen mit einem Element verknüpft sind, kann der Einrastalgorithmus intelligent entscheiden, wann und wie er einrastet, je nach Element und Größe des Scrollcontainers. Angenommen, ein Bild ist größer als das Karussell. Ein naiver Einrastalgorithmus kann verhindern, dass der Nutzer schwenkt, um das gesamte Bild zu sehen. Die Spezifikation erfordert jedoch, dass Implementierungen diesen Fall erkennen und dem Nutzer ermöglichen, frei innerhalb dieses Bildes zu scrollen und nur an den Rändern anzudocken.

Beispiel: Eine Produktseite mit Journey

Ein weiterer häufiger Fall, bei dem Scroll Snap nützlich sein kann, sind Seiten mit mehreren logischen Abschnitten, durch die vertikal gescrollt werden kann, z. B. eine typische Produktseite. scroll-snap-type: y proximity; ist für solche Fälle besser geeignet. Sie stört nicht, wenn ein Nutzer zur Mitte eines bestimmten Abschnitts scrollt, springt aber zu einem neuen Abschnitt und lenkt die Aufmerksamkeit darauf, wenn der Nutzer nah genug scrollt.

So lässt sich das erreichen:

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 -Margin

Die Produktseite hat einen fixierten Header oben. Das Design sah auch vor, dass ein Teil des oberen Bereichs sichtbar bleibt, wenn der Scrollcontainer einrastet, um den Nutzern einen Hinweis auf den Inhalt darüber zu geben.

Das Attribut scroll-padding ist ein neues CSS-Attribut, mit dem der effektive sichtbare Bereich des Scroll-Containers oder Snapports angepasst werden kann, der bei der Berechnung der Scroll-Snap-Ausrichtungen verwendet wird. Die Property definiert einen Abstand zur Padding-Box des Scrollcontainers. In unserem Beispiel wurde oben ein zusätzlicher Abstand von 15vh hinzugefügt. Dadurch wird der Browser angewiesen, eine niedrigere Position, 15vh unter dem oberen Rand des Scrollcontainers, als vertikalen Startrand für das Scroll-Andocken zu verwenden. Beim Einrasten wird die Startkante des Einrastzielelements mit dieser neuen Position bündig, sodass darüber Platz bleibt.

Mit der Property scroll-margin wird der Abstand definiert, der zum Anpassen der effektiven Box des Einrastziels verwendet wird, ähnlich wie scroll-padding im Einrast-Scrollcontainer funktioniert.

Vielleicht ist Ihnen aufgefallen, dass diese beiden Properties nicht das Wort „snap“ enthalten. Das ist beabsichtigt, da sie die Box für alle relevanten Scrollvorgänge ändern und nicht nur für das Scroll-Snap. Chrome berücksichtigt sie beispielsweise bei der Berechnung der Seitengröße für seitenweise Scrollvorgänge wie „Bild ab“ und „Bild auf“ sowie bei der Berechnung des Scrollbetrags für den Vorgang Element.scrollIntoView().

Interaktion mit anderen Scrolling-APIs

DOM Scrolling API

Scroll Snap erfolgt nach allen Scrollvorgängen, einschließlich derer, die durch ein Script initiiert wurden. Wenn Sie APIs wie Element.scrollTo verwenden, berechnet der Browser die beabsichtigte Scrollposition des Vorgangs und wendet dann die entsprechende Einrastlogik an, um die endgültige Einrastposition zu finden. Daher ist es nicht erforderlich, dass das Nutzerscript manuelle Berechnungen für das Einrasten durchführt.

Optimiertes Scrollen

Das optimierte Scrollen steuert das Verhalten eines programmatischen Scrollvorgangs, während Scroll Snap das Ziel bestimmt. 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 von Scroll Snap 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 Snap als Verbesserung hinzugefügt werden, ohne dass eine Feature-Erkennung 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 verworfenen Spezifikation vorhanden ist.

Feature-Erkennung 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 Snap kann der Scroll-Offset nach Abschluss des programmatischen Scrollens angepasst werden. Das war auch vor Scroll Snap keine gute Annahme, da das Scrollen aus anderen Gründen unterbrochen worden sein könnte. Bei Scroll Snap ist das aber besonders der Fall.

Zukünftige Funktionen

Das Scrollen stand im Mittelpunkt einer aktuellen Umfrage des Chrome-Teams. Die Umfrageergebnisse haben mehrere Bereiche aufgezeigt, in denen noch mehr getan werden muss, um die Lücke zwischen Plug-in-Bibliotheken und CSS zu schließen. Die künftige Arbeit wird sich auf scroll-snap konzentrieren, einschließlich:

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