Start · Sprachen · JavaScript · Referenz · Document: scrollsnapchanging

Document: scrollsnapchanging

Ereignis

Wird am Dokument ausgelöst, wenn der Browser während des Scrollens ein neues Snap-Ziel ermittelt, auf das beim Ende der aktuellen Scroll-Geste eingerastet würde.

seit JavaScript Chrome/Edge 129+ (nicht Baseline, experimentell) Kategorie: webapi

Signatur

document.addEventListener("scrollsnapchanging", handler)

Beschreibung

Das Ereignis scrollsnapchanging gehört zu den Scroll-Snap-Ereignissen aus CSS Scroll Snap Module Level 2. Am Document wird es ausgelöst, wenn das Dokument selbst der Scroll-Container ist, also wenn für das Wurzelelement (<html>) scroll-snap-type gesetzt ist und die Seite als Ganzes scrollt. Das Ereignis tritt auf, sobald der Browser feststellt, dass ein anderes Snap-Ziel als bisher ausgewählt würde, wenn die laufende Scroll-Geste (Wischen, Mausrad, Ziehen der Scrollleiste, Tastatur) jetzt endete.

Damit eignet sich scrollsnapchanging für sofortiges visuelles Feedback noch während des Scrollens: z. B. um den Abschnitt hervorzuheben, auf den gerade eingerastet würde, einen Indikator im Karussell zu verschieben oder eine Navigation vorab zu aktualisieren. Das Gegenstück scrollsnapchange wird erst ausgelöst, wenn das Scrollen beendet und ein neues Ziel tatsächlich eingerastet ist – dort gehören „teure“ oder endgültige Aktionen hin (Daten laden, Analytics, URL aktualisieren).

Der Handler erhält ein SnapEvent. Dessen Eigenschaften snapTargetBlock und snapTargetInline enthalten das vorläufige Snap-Ziel in Block- bzw. Inline-Richtung oder null, wenn es in dieser Achse kein Ziel gibt. Registriert wird das Ereignis per document.addEventListener("scrollsnapchanging", …) oder über die Eigenschaft document.onscrollsnapchanging. Das Ereignis ist nicht abbrechbar.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "scrollsnapchanging".
$handler Pflicht (event: SnapEvent) => void Callback, der ein SnapEvent mit snapTargetBlock und snapTargetInline (jeweils Element | null) erhält.
$options boolean | AddEventListenerOptions false Übliche Listener-Optionen wie passive, once oder signal.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler bekommt ein SnapEvent-Objekt übergeben.

Beispiele

Anstehenden Abschnitt beim Scrollen hervorheben

// CSS: html { scroll-snap-type: y mandatory; }
//      section { scroll-snap-align: start; height: 100vh; }
let pending = null;

document.addEventListener("scrollsnapchanging", (event) => {
  pending?.classList.remove("is-pending");
  pending = event.snapTargetBlock;
  pending?.classList.add("is-pending");
  console.log("Würde einrasten auf:", pending?.id);
});
Würde einrasten auf: kapitel-2

Über die on-Property mit Seiten-Indikator

const dots = document.querySelectorAll(".pager-dot");
const sections = [...document.querySelectorAll("section")];

document.onscrollsnapchanging = (event) => {
  const index = sections.indexOf(event.snapTargetBlock);
  dots.forEach((dot, i) => dot.classList.toggle("active", i === index));
};

// Handler wieder entfernen:
// document.onscrollsnapchanging = null;

Feature-Erkennung, Kombination mit scrollsnapchange und Entfernen

const onChanging = (e) => {
  document.body.dataset.preview = e.snapTargetBlock?.id ?? "";
};
const onChange = (e) => {
  // Endgültige Aktion erst nach dem Einrasten
  history.replaceState(null, "", `#${e.snapTargetBlock?.id ?? ""}`);
};

if ("onscrollsnapchanging" in document) {
  document.addEventListener("scrollsnapchanging", onChanging);
  document.addEventListener("scrollsnapchange", onChange);
} else {
  console.log("Scroll-Snap-Events nicht unterstützt – Fallback per IntersectionObserver");
}

// Später aufräumen:
const cleanup = () => {
  document.removeEventListener("scrollsnapchanging", onChanging);
  document.removeEventListener("scrollsnapchange", onChange);
};

// Wichtig · Fallstricke

  • Browser-Unterstützung: Bisher nur in Chromium-Browsern (Chrome/Edge ab 129). Firefox und Safari unterstützen das Ereignis derzeit nicht – immer per "onscrollsnapchanging" in document prüfen und ggf. auf IntersectionObserver oder scrollend ausweichen.
  • Am Document kommt das Ereignis nur an, wenn das Dokument selbst der Snap-Container ist (scroll-snap-type auf html). Für innere Container den Listener direkt am jeweiligen Element registrieren.
  • Das Ereignis kann während einer einzigen Geste mehrfach feuern, wenn der Nutzer hin- und herscrollt. Keine aufwendigen Operationen (Netzwerkaufrufe, Layout-lastige DOM-Änderungen) im Handler – dafür ist scrollsnapchange gedacht.
  • Das vorläufige Ziel wird nicht zwingend das endgültige: Endet die Geste anders, feuert ggf. erneut scrollsnapchanging mit dem ursprünglichen Ziel.
  • snapTargetBlock/snapTargetInline können null sein – immer optional verketten (?.).