Verwendung von Scroll-Snap-Ereignissen
Das Modul CSS Scroll Snap definiert zwei Scroll-Snap-Ereignisse: scrollsnapchanging
und scrollsnapchange
. Diese ermöglichen die Ausführung von JavaScript als Reaktion darauf, dass der Browser feststellt, dass neue Scroll-Snap-Ziele ausstehend beziehungsweise ausgewählt sind.
Dieser Leitfaden bietet einen Überblick über diese Ereignisse zusammen mit vollständigen Beispielen.
Überblick über die Ereignisse
Scroll-Snap-Ereignisse werden auf einem Scroll-Container gesetzt, der potenzielle Scroll-Snap-Ziele enthält:
-
Das Ereignis
scrollsnapchanging
wird ausgelöst, wenn der Browser feststellt, dass ein neues Scroll-Snap-Ziel gewählt wird, wenn die aktuelle Scroll-Geste endet. Dies ist das ausstehende Scroll-Snap-Ziel. Genauer gesagt wird dieses Ereignis während einer Scroll-Geste ausgelöst, jedes Mal, wenn der Benutzer über potenzielle neue Snap-Ziele bewegt wird. Während dasscrollsnapchanging
-Ereignis möglicherweise mehrmals für jede Scroll-Geste ausgelöst wird, wird es nicht bei allen potenziellen Snap-Zielen für eine Scroll-Geste ausgelöst, die über mehrere Snap-Ziele hinweg geht. Es wird vielmehr nur für das letzte Ziel ausgelöst, auf dem das Snapping potenziell zur Ruhe kommt. -
Das Ereignis
scrollsnapchange
wird am Ende einer Scroll-Operation ausgelöst, wenn ein neues Scroll-Snap-Ziel ausgewählt wird. Genauer gesagt wird dieses Ereignis ausgelöst, wenn eine Scroll-Geste abgeschlossen ist, jedoch nur, wenn ein neues Snap-Ziel ausgewählt wird. Dieses Ereignis wird kurz vor dem Ereignisscrollend
ausgelöst.
Schauen wir uns ein Beispiel an, das die beiden Ereignisse in Aktion zeigt (wie dies später im Artikel aufgebaut wird, werden Sie sehen):
Probieren Sie aus, die Liste der Kästchen hinauf und hinab zu scrollen:
- Versuchen Sie, den Container langsam auf und ab zu scrollen, ohne die Scroll-Geste loszulassen. Ziehen Sie zum Beispiel Ihre Finger über den Scroll-Bereich auf einem Touch-Device oder Trackpad oder halten Sie die Maustaste auf der Scroll-Leiste gedrückt und bewegen Sie die Maus. Die Kästchen, über die Sie sich bewegen, sollten sich beim Überfahren mit dunklerer grauer Farbe färben und dann wieder in ihre normale Farbe zurückkehren, wenn Sie sich wieder von ihnen weg bewegen. Dies ist das
scrollsnapchanging
-Ereignis in Aktion. - Versuchen Sie nun, die Scroll-Geste loszulassen; das nächstgelegene Kästchen zu Ihrer Scroll-Position sollte sich in eine lila Farbe mit weißem Text animieren. Die Animation tritt auf, wenn das
scrollsnapchange
-Ereignis ausgelöst wird. - Versuchen Sie schließlich, schnell zu scrollen. Schleudern Sie zum Beispiel den Finger kräftig über den Bildschirm, um mehrere potenzielle Ziele zu passieren, bevor Sie in der Nähe eines Ziels weiter unten im Scroll-Container zur Ruhe kommen. Sie sollten nur ein
scrollsnapchanging
-Ereignis sehen, das ausgelöst wird, wenn das Scrollen beginnt, sich zu verlangsamen, bevor dasscrollsnapchange
-Ereignis ausgelöst wird und das ausgewählte Snap-Ziel lila wird.
Das SnapEvent
-Ereignisobjekt
Beide der oben genannten Ereignisse teilen das SnapEvent
-Ereignisobjekt. Dieses hat zwei Eigenschaften, die der Funktionsweise von Scroll-Snap-Ereignissen entscheidend sind:
snapTargetBlock
gibt eine Referenz auf das Element zurück, zu dem im Blockrichtung beim Ereignisauslöser geschnappt wurde, odernull
, wenn das Scroll-Snapping nur in der Inlinerichtung erfolgt, sodass kein Element in der Blockrichtung geschnappt wird.snapTargetInline
gibt eine Referenz auf das Element zurück, zu dem im Inlinerichtung beim Ereignisauslöser geschnappt wurde, odernull
, wenn das Scroll-Snapping nur in der Blockrichtung erfolgt, sodass kein Element in der Inlinerichtung geschnappt wird.
Diese Eigenschaften ermöglichen es Ereignishandler-Funktionen, das Element zu melden, das geschnappt wurde (im Fall von scrollsnapchange
) oder das Element, das geschnappt würde, wenn die Scroll-Geste jetzt beendet wäre (im Fall von scrollsnapchanging
) — in einer oder zwei Dimensionen. Sie können diese Elemente dann auf jede gewünschte Weise manipulieren, indem Sie beispielsweise direkt Stile auf ihnen über ihre style
-Eigenschaften setzen, Klassen auf sie anwenden, die Stile in einem Stylesheet definiert haben, usw.
Beziehung mit CSS scroll-snap-type
Die auf SnapEvent
verfügbaren Eigenschaftswerte entsprechen direkt dem Wert der CSS-Eigenschaft scroll-snap-type
, die auf den Scroll-Container gesetzt ist:
- Wenn die Snap-Achse als
block
(oder ein physikalischer Achsenwert, derblock
im aktuellen Schreibmodus entspricht) angegeben ist, gibt nursnapTargetBlock
eine Elementreferenz zurück. - Wenn die Snap-Achse als
inline
(oder ein physikalischer Achsenwert, derinline
im aktuellen Schreibmodus entspricht) angegeben ist, gibt nursnapTargetInline
eine Elementreferenz zurück. - Wenn die Snap-Achse als
both
angegeben ist, gebensnapTargetBlock
undsnapTargetInline
eine Elementreferenz zurück.
Umgang mit eindimensionalen Scrollern
Wenn Sie es mit einem horizontalen Scroller zu tun haben, ändert sich nur die Eigenschaft snapTargetInline
des Ereignisobjekts, wenn sich das gesnappte Element ändert, falls der Inhalt einen horizontalen writing-mode
hat, oder die Eigenschaft snapTargetBlock
, falls der Inhalt einen vertikalen writing-mode
hat.
Umgekehrt ändert sich bei einem vertikalen Scroller nur die Eigenschaft snapTargetBlock
, wenn sich das gesnappte Element ändert, falls der Inhalt einen horizontalen writing-mode
hat, oder die Eigenschaft snapTargetInline
, falls der Inhalt einen vertikalen writing-mode
hat.
In beiden Fällen gibt die nicht ändernde Eigenschaft der beiden null
zurück.
Schauen wir uns ein Beispiel-Snippet an, um eine typische eindimensionale Scroll-Snap-Ereignishandlerfunktion zu zeigen:
scrollingElem.addEventListener("scrollsnapchange", (event) => {
event.snapTargetBlock.className = "select-section";
});
In diesem Snippet wird eine scrollsnapchange
-Handlerfunktion auf einem Blockrichtungs-Scroll-Container-Element gesetzt, in dem Snap-Ziele erscheinen. Wenn das Ereignis ausgelöst wird, setzen wir eine select-section
-Klasse auf das snapTargetBlock
-Element, das verwendet werden könnte, um ein neu ausgewähltes Snap-Ziel so zu stylen, dass es so aussieht, als wäre es ausgewählt worden (zum Beispiel mit einer Animation).
Umgang mit zweidimensionalen Scrollern
Wenn Sie es mit einem horizontalen und vertikalen Scroller zu tun haben, wird der Code komplexer. Das liegt daran, dass sowohl der Wert der Eigenschaft snapTargetBlock
als auch der Wert der Eigenschaft snapTargetInline
eine Elementreferenz zurückgeben (keine gibt null
zurück), und eine der beiden Werte wird sich ändern, abhängig davon, in welche Richtung Sie scrollen und vom writing-mode
des Inhalts:
- Wenn der Scroller horizontal gescrollt wird, ändert sich die Eigenschaft
snapTargetInline
, wenn sich das gesnappte Element ändert, falls der Inhalt einen horizontalenwriting-mode
hat, oder die EigenschaftsnapTargetBlock
, falls der Inhalt einen vertikalenwriting-mode
hat. - Wenn der Scroller vertikal gescrollt wird, ändert sich die Eigenschaft
snapTargetBlock
, wenn sich das gesnappte Element ändert, falls der Inhalt einen horizontalenwriting-mode
hat, oder die EigenschaftsnapTargetInline
, falls der Inhalt einen vertikalenwriting-mode
hat.
Um dies zu handhaben, werden Sie wahrscheinlich verfolgen müssen, ob es das snapTargetBlock
- oder das snapTargetInline
-Element war, das sich geändert hat. Schauen wir uns ein Beispiel an:
const prevState = {
snapTargetInline: "s1",
snapTargetBlock: "s1",
};
scrollingElem.addEventListener("scrollsnapchange", (event) => {
if (!(prevState.snapTargetBlock === event.snapTargetBlock.id)) {
console.log(
`The container was scrolled in the block direction to element ${event.snapTargetBlock.id}`,
);
}
if (!(prevState.snapTargetInline === event.snapTargetInline.id)) {
console.log(
`The container was scrolled in the block direction to element ${event.snapTargetBlock.id}`,
);
}
prevState.snapTargetBlock = event.snapTargetBlock.id;
prevState.snapTargetInline = event.snapTargetInline.id;
});
In diesem Snippet definieren wir zuerst ein Objekt (prevState
), das die ID der vorherigen snapTargetBlock
- und snapTargetInline
-Elemente speichert.
In der Ereignishandlerfunktion verwenden wir if
-Anweisungen, um zu testen, ob:
- Die ID von
prevState.snapTargetBlock
gleich der ID des aktuellenevent.snapTargetBlock
-Elements ist. - Die ID von
prevState.snapTargetInline
gleich der ID des aktuellenevent.snapTargetInline
-Elements ist.
Wenn die Werte unterschiedlich sind, bedeutet dies, dass der Scroller in dieser Richtung (block oder inline) gescrollt wurde, und wir loggen eine Nachricht in die Konsole, um dies anzuzeigen. In einem echten Beispiel würden Sie wahrscheinlich das gesnappte Element auf irgendeine Weise stylen, um anzuzeigen, dass es gesnappt wurde.
Wir aktualisieren dann die Werte von prevState.snapTargetBlock
und prevState.snapTargetInline
für den nächsten Lauf der Ereignishandlerfunktion.
Im Rest dieses Artikels werden wir uns ein paar vollständige Scroll-Snap-Ereignisbeispiele anschauen, mit denen Sie in den live gerenderten Versionen am Ende jedes Abschnitts spielen können.
Eindimensionales Scroll-Beispiel
Dieses Beispiel bietet ein vertikal scrollendes <main>
-Element, das mehrere hellgraue <section>
-Elemente enthält, die alle Scroll-Snap-Ziele sind. Wenn ein neues Snap-Ziel aussteht, wird es eine dunklere Grauschattierung annehmen. Wenn ein neues Snap-Ziel ausgewählt wird, wird es sanft zu Lila mit weißem Text animieren. Wenn zuvor ein anderes Snap-Ziel ausgewählt war, wird es sanft zurück zu Grau mit schwarzem Text animieren.
HTML
Das HTML für das Beispiel besteht aus einem einzelnen <main>
-Element. Wir werden die <section>
-Elemente später dynamisch mit JavaScript hinzufügen, um Platz auf der Seite zu sparen.
<main></main>
CSS
Im CSS beginnen wir mit einem dicken schwarzen border
für das <main>
-Element und einer festen width
und height
. Wir setzen seinen overflow
-Wert auf scroll
, sodass überlaufender Inhalt verborgen wird und gescrollt werden kann, und setzen scroll-snap-type
auf block mandatory
, damit Snap-Ziele nur in der Blockrichtung immer gesnappt werden.
main {
border: 3px solid black;
width: 250px;
height: 450px;
overflow: scroll;
scroll-snap-type: block mandatory;
}
Jedes <section>
-Element erhält einen margin
von 50px
, um die <section>
-Elemente zu trennen und das Scroll-Snap-Verhalten deutlicher zu machen. Wir setzen dann scroll-snap-align
auf center
, um anzugeben, dass wir in die Mitte jedes Snap-Ziels snappen möchten. Schließlich wenden wir eine transition
an, um die Stiländerungen, die angewendet werden, wenn eine Snap-Ziel-Auswahl getroffen wurde oder aussteht, sanft zu animieren.
section {
margin: 50px auto;
scroll-snap-align: center;
transition: 0.5s ease;
}
Die oben erwähnten Stiländerungen werden durch Klassen angewendet, die mithilfe von JavaScript auf die <section>
-Elemente angewendet werden. Die select-section
-Klasse wird angewendet, um eine Auswahl zu signalisieren — sie setzt einen lila Hintergrund und weiße Textfarbe. Die pending
-Klasse wird angewendet, um eine ausstehende Snap-Ziel-Auswahl zu signalisieren — sie färbt den Hintergrund der Zielauswahl dunkler grau.
.pending {
background-color: #ccc;
}
.select-section {
background: purple;
color: white;
}
JavaScript
Im JavaScript beginnen wir damit, eine Referenz auf das <main>
-Element zu erhalten und die Anzahl der <section>
-Elemente zu definieren, die generiert werden sollen (in diesem Fall 21), sowie eine Variable, um zu zählen. Anschließend verwenden wir eine while
-Schleife, um die <section>
-Elemente zu generieren, wobei jedem ein Kind h2
mit einem Text zugewiesen wird, der Section
plus den aktuellen Wert von n
liest.
const mainElem = document.querySelector("main");
const sectionCount = 21;
let n = 1;
while (n <= sectionCount) {
mainElem.innerHTML += `
<section>
<h2>Section ${n}</h2>
</section>
`;
n++;
}
Kommen wir nun zur Event-Handler-Funktion für das scrollsnapchanging
-Ereignis. Wenn ein Kind des <main>
-Elements (d.h. eines der <section>
-Elemente) zu einem ausstehenden Snap-Ziel wird, führen wir Folgendes aus:
- Prüfen, ob ein Element zuvor die
pending
-Klasse angewendet hatte und, falls ja, diese entfernen. So soll nur das aktuell ausstehende Ziel diepending
-Klasse erhalten und dunkler grau gefärbt werden. Wir wollen nicht, dass zuvor ausstehende Ziele, die nicht mehr ausstehen, das Styling behalten. - Dem durch die
snapTargetBlock
-Eigenschaft referenzierten Element (welches eines der<section>
-Elemente sein wird) diepending
-Klasse geben, sodass es dunkler grau wird.
mainElem.addEventListener("scrollsnapchanging", (event) => {
const previousPending = document.querySelector(".pending");
if (previousPending) {
previousPending.classList.remove("pending");
}
event.snapTargetBlock.classList.add("pending");
});
Hinweis:
In diesem Demo brauchen wir uns nicht um die Eigenschaft snapTargetInline
des Ereignisobjekts zu kümmern — wir scrollen nur vertikal und das Demo verwendet einen horizontalen Schreibmodus, daher wird sich nur der Wert von snapTargetBlock
ändern. In diesem Fall gibt snapTargetInline
immer null
zurück.
Wenn eine Scroll-Geste endet und ein <section>
-Element tatsächlich als Snap-Ziel ausgewählt wird, wird die Event-Handler-Funktion für das scrollsnapchange
-Ereignis ausgelöst. Diese führt Folgendes aus:
- Prüfen, ob zuvor ein Snap-Ziel ausgewählt war — d.h. ob eine
select-section
-Klasse zuvor auf ein Element angewendet wurde. Wenn ja, entfernen wir sie. - Die
select-section
-Klasse auf das durch diesnapTargetBlock
-Eigenschaft referenzierte<section>
-Element anwenden, sodass das Snap-Ziel, das gerade ausgewählt wurde, die Auswahl-Animation angewendet bekommt.
mainElem.addEventListener("scrollsnapchange", (event) => {
const currentlySnapped = document.querySelector(".select-section");
if (currentlySnapped) {
currentlySnapped.classList.remove("select-section");
}
event.snapTargetBlock.classList.add("select-section");
});
Ergebnis
Versuchen Sie, den Scroll-Container nach oben und unten zu scrollen und das oben beschriebene Verhalten zu beobachten:
Zweidimensionales Scroll-Beispiel
Dieses Beispiel ist dem vorherigen ähnlich, mit dem Unterschied, dass es ein horizontal und vertikal scrollendes <main>
-Element enthält, das mehrere hellgraue <section>
-Elemente enthält, die alle Snap-Ziele sind.
Das HTML für das Beispiel ist das gleiche wie beim vorherigen Beispiel — ein einzelnes <main>
-Element.
CSS
Das CSS für dieses Beispiel ist dem CSS im vorherigen Beispiel ähnlich. Die bedeutendsten Unterschiede sind wie folgt.
Schauen wir zuerst auf das Styling des <main>
-Elements. Wir möchten, dass die <section>
-Elemente als Gitter angeordnet werden, daher verwenden wir das CSS-Gitter-Layout, um anzugeben, dass wir sie in sieben Spalten darstellen möchten, mit einem grid-template-columns
-Wert von repeat(7, 1fr)
. Wir geben auch den Raum um die <section>
-Elemente an, indem wir padding
und gap
auf das <main>
-Element setzen, anstatt margin
auf die <section>
-Elemente.
Schließlich, da wir in diesem Beispiel in beiden Richtungen scrollen, setzen wir scroll-snap-type
auf both mandatory
, sodass Snap-Ziele sowohl in der Blockrichtung als auch in der Inlinerichtung immer gesnappt werden.
main {
display: grid;
grid-template-columns: repeat(7, 1fr);
padding: 100px;
gap: 50px;
overflow: scroll;
border: 3px solid black;
width: 350px;
height: 350px;
scroll-snap-type: both mandatory;
}
Als nächstes werden wir in diesem Beispiel CSS-Animationen anstelle von Übergängen verwenden. Dies führt zu komplexerem Code, ermöglicht jedoch eine feinere Kontrolle über die angewendeten Animationen.
Wir definieren zuerst die Klassen, die angewendet werden, um zu signalisieren, dass eine Snap-Ziel-Auswahl getroffen oder aussteht. Die select-section
- und deselect-section
-Klassen werden Keyframe-Animationen anwenden, um eine Auswahl oder Deselektion anzuzeigen. Die pending
-Klasse wird angewendet, um eine ausstehende Snap-Ziel-Auswahl anzuzeigen (sie färbt den Hintergrund der Auswahl, wie im vorherigen Beispiel, in dunkleres Grau).
Die @keyframes
animieren von einem grauen Hintergrund und schwarzem (Standard-)Text zu einem lila Hintergrund und weißem Text und zurück, jeweils. Die letzte Animation ist etwas anders als die erste — sie verwendet auch opacity
, um einen Ausblende-/Einblendeffekt zu erzeugen.
.select-section {
animation: select 0.8s ease forwards;
}
.deselect-section {
animation: deselect 0.8s ease forwards;
}
.pending {
background-color: #ccc;
}
@keyframes select {
from {
background: #eee;
color: black;
}
to {
background: purple;
color: white;
}
}
@keyframes deselect {
0% {
background: purple;
color: white;
opacity: 1;
}
80% {
background: #eee;
color: black;
opacity: 0.1;
}
100% {
background: #eee;
color: black;
opacity: 1;
}
}
JavaScript
Im JavaScript beginnen wir wie im vorherigen Beispiel, außer dass wir diesmal 49 <section>
-Elemente generieren und jedem eine ID von s
plus dem aktuellen Wert von n
zuweisen, um sie später leichter verfolgen zu können. Mit dem oben angegebenen CSS-Gitter-Layout haben wir sieben Spalten von jeweils sieben <section>
-Elementen.
const mainElem = document.querySelector("main");
const sectionCount = 49;
let n = 1;
while (n <= sectionCount) {
mainElem.innerHTML += `
<section id="s${n}">
<h2>Section ${n}</h2>
</section>
`;
n++;
}
Anschließend geben wir ein Objekt namens prevState
an, welches uns ermöglicht, das zuvor ausgewählte Snap-Ziel jederzeit zu verfolgen — seine Eigenschaften speichern die IDs der vorherigen Inline- und Block-Snap-Ziele. Dies ist wichtig, um herauszufinden, ob wir jedes Mal den neuen Block-Zielpunkt oder den neuen Inline-Zielpunkt stylen müssen, wenn ein Ereignishandler ausgelöst wird.
const prevState = {
snapTargetInline: "s1",
snapTargetBlock: "s1",
};
Beispielsweise nehmen wir an, der Scroll-Container wird so gescrollt, dass sich die ID des neuen SnapEvent.snapTargetBlock
-Elements geändert hat (sie entspricht nicht der in prevState.snapTargetBlock
gespeicherten ID), aber die ID des neuen SnapEvent.snapTargetInline
-Elements ist immer noch dieselbe wie die in prevState.snapTargetInline
gespeicherte ID. Dies bedeutet, dass wir zu einem neuen Snap-Ziel in der Blockrichtung gewechselt haben, daher sollten wir SnapEvent.snapTargetBlock
stylen, aber wir sind nicht zu einem neuen Snap-Ziel in der Inlinerichtung gewechselt, daher sollten wir SnapEvent.snapTargetInline
nicht stylen.
In diesem Fall beschreiben wir zuerst die Event-Handler-Funktion für das scrollsnapchange
-Ereignis. In dieser Funktion:
- Beginnen wir damit sicherzustellen, dass bei einem zuvor ausgewählten
<section>
-Element, das als Snap-Ziel ausgewählt wurde (angezeigt durch das Vorhandensein derselect-section
-Klasse), diedeselect-section
-Klasse angewendet wird, um die Deselektionsanimation zu zeigen. Wenn kein Snap-Ziel zuvor ausgewählt war, wenden wir dieselect-section
-Klasse auf das erste<section>
-Element im DOM an, sodass es als ausgewählt angezeigt wird, wenn die Seite zuerst geladen wird. - Vergleichen wir die zuvor ausgewählte Snap-Ziel-ID mit der neu ausgewählten Snap-Ziel-ID, sowohl für die Block- als auch die Inlinerichtung. Wenn sie unterschiedlich sind, bedeutet dies, dass sich die Auswahl geändert hat, und wir wenden die
select-section
-Klasse auf das entsprechende Snap-Ziel an, um dies visuell anzuzeigen. - Aktualisieren wir
prevState.snapTargetBlock
undprevState.snapTargetInline
, damit diese gleich den IDs der Scroll-Snap-Ziele sind, die gerade ausgewählt wurden, sodass sie beim nächsten Auslösen des Ereignisses die vorherigen Auswahlen sind.
mainElem.addEventListener("scrollsnapchange", (event) => {
if (document.querySelector(".select-section")) {
document.querySelector(".select-section").className = "deselect-section";
} else {
document.querySelector("section").className = "select-section";
}
if (!(prevState.snapTargetBlock === event.snapTargetBlock.id)) {
event.snapTargetBlock.className = "select-section";
}
if (!(prevState.snapTargetInline === event.snapTargetInline.id)) {
event.snapTargetInline.className = "select-section";
}
prevState.snapTargetBlock = event.snapTargetBlock.id;
prevState.snapTargetInline = event.snapTargetInline.id;
});
Wenn die Event-Handler-Funktion für das scrollsnapchanging
-Ereignis ausgelöst wird, führen wir Folgendes aus:
- Entfernen wir die
pending
-Klasse vom Element, dem diese zuvor angewendet wurde, sodass nur das aktuelle ausstehende Ziel diepending
-Klasse erhält und dunkler grau gefärbt wird. - Geben wir dem aktuellen ausstehenden Element die
pending
-Klasse, sodass es dunkler grau wird, jedoch nur, wenn es noch nicht dieselect-section
-Klasse hat — wir möchten, dass ein zuvor ausgewähltes Ziel das lila Auswahldesign beibehält, bis tatsächlich ein neues Ziel ausgewählt wird. Wir fügen auch eine zusätzliche Prüfung in dieif
-Anweisungen ein, um sicherzustellen, dass wir nur das inline oder block ausstehende Snap-Ziel stylen, je nachdem, welches sich geändert hat. Wieder vergleichen wir das vorherige Snap-Ziel mit dem aktuellen Snap-Ziel in jedem Fall.
mainElem.addEventListener("scrollsnapchanging", (event) => {
const previousPending = document.querySelector(".pending");
if (previousPending) {
previousPending.className = "";
}
if (
!(event.snapTargetBlock.className === "select-section") &&
!(prevState.snapTargetBlock === event.snapTargetBlock.id)
) {
event.snapTargetBlock.className = "pending";
}
if (
!(event.snapTargetInline.className === "select-section") &&
!(prevState.snapTargetInline === event.snapTargetInline.id)
) {
event.snapTargetInline.className = "pending";
}
});
Ergebnis
Versuchen Sie, horizontal und vertikal im Scroll-Container zu scrollen und das oben beschriebene Verhalten zu beobachten:
Scroll-Snap-Ereignisse auf Document
und Window
In diesem Artikel haben wir die Scroll-Snap-Ereignisse behandelt, die auf der Element
-Schnittstelle ausgelöst werden, aber die gleichen Ereignisse werden auch auf den Objekten Document
und Window
ausgelöst. Siehe:
Document
-Ereignisreferenzen fürscrollsnapchange
undscrollsnapchanging
.Window
-Ereignisreferenzen fürscrollsnapchange
undscrollsnapchanging
.
Diese funktionieren auf dieselbe Weise wie die Element
-Versionen, mit dem Unterschied, dass das gesamte HTML-Dokument als Scroll-Snap-Container festgelegt werden muss (d.h. scroll-snap-type
ist auf dem <html>
-Element gesetzt).
Zum Beispiel, wenn wir ein ähnliches Beispiel wie die oben beschriebenen verwenden, bei dem wir ein <main>
-Element mit signifikantem Inhalt haben:
<main>
<!-- Significant content -->
</main>
Das <main>
-Element könnte mithilfe einer Kombination aus CSS-Eigenschaften in einen Scroll-Container umgewandelt werden:
main {
width: 250px;
height: 450px;
overflow: scroll;
}
Sie könnten dann das Scroll-Snapping-Verhalten auf dem scrollenden Inhalt implementieren, indem Sie die scroll-snap-type
-Eigenschaft auf das <html>
-Element festlegen:
html {
scroll-snap-type: block mandatory;
}
Das folgende JavaScript-Snippet würde dazu führen, dass das scrollsnapchange
-Ereignis auf dem HTML-Dokument ausgelöst wird, wenn ein Kind des <main>
-Elements zu einem neu ausgewählten Snap-Ziel wird. In der Handler-Funktion setzen wir eine selected
-Klasse auf das Kind, das durch die SnapEvent.snapTargetBlock
referenziert wird, die verwendet werden könnte, um es so zu stylen, dass es aussieht, als wäre es ausgewählt worden (zum Beispiel mit einer Animation), wenn das Ereignis ausgelöst wird.
document.addEventListener("scrollsnapchange", (event) => {
event.snapTargetBlock.classList.add("selected");
});
Wir könnten das Ereignis stattdessen auf Window
auslösen, um dieselbe Funktionalität zu erreichen:
window.addEventListener("scrollsnapchange", (event) => {
event.snapTargetBlock.classList.add("selected");
});
Siehe auch
scrollsnapchanging
Ereignisscrollsnapchange
EreignisSnapEvent
- CSS Scroll Snap Modul
- Scroll Snap Events auf developer.chrome.com (2024)