Start · Sprachen · JavaScript · Referenz · Window: scrollsnapchange

Window: scrollsnapchange

Ereignis

Wird am <code>window</code> ausgelöst, wenn am Ende eines Scrollvorgangs im Dokument-Scrollcontainer ein neues Scroll-Snap-Ziel feststeht.

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

Signatur

window.addEventListener("scrollsnapchange", handler)

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}`);
});
Eingerastet auf: #kapitel-2

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)
Folie 1 intro Folie 2 ende Listener entfernt

// 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 window und sehen Sie einen Fallback vor, etwa mit IntersectionObserver oder scrollend.
  • Am window kommt das Ereignis nur an, wenn scroll-snap-type auf dem Wurzelelement (html) gesetzt ist. Bei body oder einem anderen Container lauschen Sie auf diesem Element. Weil das Ereignis nicht aufsteigt, erreicht es window dann 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.
  • snapTargetBlock bzw. snapTargetInline können null sein, zum Beispiel wenn nur eine Achse einrastet. Prüfen Sie den Wert daher immer vorher.
  • Beim ersten Laden der Seite wird kein scrollsnapchange ausgelöst. Das anfängliche Snap-Ziel müssen Sie selbst bestimmen.