Signatur
Beschreibung
Das Ereignis scrollsnapchange gehört zur CSS-Scroll-Snap-Erweiterung. Am window wird es ausgelöst, wenn das Wurzelelement des Dokuments (<html>) der Scroll-Snap-Container ist und nach einem abgeschlossenen Scrollvorgang ein anderes Element als Snap-Ziel feststeht als vorher. Das gilt für Scrollen mit dem Finger, Mausrad, Tastatur oder Scrollbalken und auch für programmatisches Scrollen.
Der Handler bekommt ein SnapEvent. Dessen Eigenschaften snapTargetBlock und snapTargetInline enthalten das neue Snap-Ziel in Block- bzw. Inline-Richtung. Gibt es in einer Achse kein Snap-Ziel, ist der Wert null. Das Ereignis steigt nicht auf (kein Bubbling) und lässt sich nicht abbrechen.
Typische Einsatzfälle sind Vollbild-Präsentationen, Onboarding-Seiten oder Abschnitt-Layouts mit scroll-snap-type auf html. Nach jedem Einrasten kann man die Navigation hervorheben, den URL-Hash aktualisieren, Analysedaten senden oder Inhalte nachladen. Früher ging das nur mit IntersectionObserver oder mit scroll-/scrollend-Handlern samt eigener Berechnung.
Neben addEventListener() gibt es die Handler-Eigenschaft window.onscrollsnapchange. Soll dagegen ein einzelnes Element mit overflow der Scroll-Container sein, registriert man das Ereignis direkt auf diesem Element (Element: scrollsnapchange).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Ereignisname: "scrollsnapchange". |
|
| $handler Pflicht | (event: SnapEvent) => void | Callback, der ein SnapEvent mit snapTargetBlock und snapTargetInline (jeweils Element | null) bekommt. |
|
| $options | boolean | AddEventListenerOptions | false | Optionale Einstellungen wie once, passive oder signal (zum Entfernen per AbortController). |
Beispiele
Aktiven Abschnitt nach dem Einrasten ermitteln
// Wurzel-Scroll-Container mit Snap-Verhalten einrichten
document.documentElement.style.scrollSnapType = 'y mandatory';
document.querySelectorAll('section').forEach((s) => {
s.style.scrollSnapAlign = 'start';
s.style.minHeight = '100vh';
});
window.addEventListener('scrollsnapchange', (event) => {
const target = event.snapTargetBlock;
if (!target) return;
console.log(`Eingerastet auf: #${target.id}`);
// URL-Hash aktualisieren, ohne neu zu scrollen
history.replaceState(null, '', `#${target.id}`);
});
Navigation hervorheben über window.onscrollsnapchange (mit Feature-Erkennung)
const navLinks = document.querySelectorAll('nav a');
if ('onscrollsnapchange' in window) {
window.onscrollsnapchange = ({ snapTargetBlock }) => {
navLinks.forEach((link) => {
const active = snapTargetBlock && link.hash === `#${snapTargetBlock.id}`;
link.classList.toggle('aktiv', Boolean(active));
});
};
} else {
console.warn('scrollsnapchange nicht unterstützt – Fallback per IntersectionObserver nötig');
}
Listener per AbortController wieder entfernen
const controller = new AbortController();
let gesehen = 0;
window.addEventListener('scrollsnapchange', (event) => {
gesehen += 1;
console.log('Folie', gesehen, event.snapTargetBlock?.dataset.folie);
// Nach der letzten Folie nicht mehr lauschen
if (event.snapTargetBlock?.dataset.folie === 'ende') {
controller.abort();
console.log('Listener entfernt');
}
}, { signal: controller.signal });
// Alternative: window.removeEventListener('scrollsnapchange', handler)
// Wichtig · Fallstricke
- Browser-Unterstützung: Das Ereignis ist experimentell und bisher nur in Chromium-Browsern (ab Chrome/Edge 129) verfügbar, nicht in Firefox und Safari. Prüfen Sie vorher mit
'onscrollsnapchange' in windowund sehen Sie einen Fallback vor, etwa mitIntersectionObserveroderscrollend. - Am
windowkommt das Ereignis nur an, wennscroll-snap-typeauf dem Wurzelelement (html) gesetzt ist. Beibodyoder einem anderen Container lauschen Sie auf diesem Element. Weil das Ereignis nicht aufsteigt, erreicht eswindowdann nicht. - Das Ereignis wird erst nach dem Ende des Scrollvorgangs ausgelöst, und nur, wenn sich das Snap-Ziel tatsächlich geändert hat. Scrollt man zurück zum selben Ziel, passiert nichts. Für Rückmeldung schon während des Scrollens gibt es
scrollsnapchanging. snapTargetBlockbzw.snapTargetInlinekönnennullsein, zum Beispiel wenn nur eine Achse einrastet. Prüfen Sie den Wert daher immer vorher.- Beim ersten Laden der Seite wird kein
scrollsnapchangeausgelöst. Das anfängliche Snap-Ziel müssen Sie selbst bestimmen.