Start · Sprachen · JavaScript · Referenz · SnapEvent

SnapEvent

Schnittstelle

Ereignisobjekt der Events <code>scrollsnapchanging</code> und <code>scrollsnapchange</code>. Es nennt die Elemente, auf die ein Scroll-Snap-Container in Block- und Inline-Richtung einrastet.

seit JavaScript Chrome/Edge 129+, noch nicht in Firefox und Safari Kategorie: webapi

Signatur

interface SnapEvent extends Event

Beschreibung

SnapEvent ist das Ereignisobjekt für die beiden Scroll-Snap-Events der CSS Scroll Snap Module Level 2. Ein Scroll-Container, dessen Kinder per scroll-snap-type und scroll-snap-align Einrastpunkte festlegen, löst diese Events aus:

  • scrollsnapchanging feuert während der Scrollgeste, sobald der Browser ein anderes Element als künftiges Einrastziel erwartet. So lässt sich schon beim Wischen eine Vorschau zeigen, etwa ein Punkt in der Seitennavigation eines Karussells.
  • scrollsnapchange feuert nach dem Scrollvorgang, wenn ein neues Einrastziel feststeht. Das passiert kurz vor scrollend. Hier gehören endgültige Zustandsänderungen hin, etwa „aktive Folie“, Nachladen von Inhalten oder Statistik.

Neben den von Event geerbten Eigenschaften hat SnapEvent zwei nur lesbare Eigenschaften: snapTargetBlock nennt das Element, auf das in Block-Richtung eingerastet wird (bei horizontaler Schreibweise also vertikal). snapTargetInline nennt das Element in Inline-Richtung (horizontal). Ist in einer Richtung kein Einrasten eingestellt oder gibt es kein Ziel, ist der Wert null.

Vorher musste man Scrollpositionen mit scroll-Listenern, IntersectionObserver oder getBoundingClientRect() selbst auswerten. Das Einrastziel war damit nur geschätzt. SnapEvent meldet dagegen direkt das Ziel, das die Rendering-Engine tatsächlich gewählt hat. Die Events werden am Scroll-Container ausgelöst. Scrollt das gesamte Dokument, kommen sie am document an und steigen bis zum window auf.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Konstruktor-Parameter: Name des Events, "scrollsnapchanging" oder "scrollsnapchange".
$options object {} Konstruktor-Parameter: ein Objekt mit allen Optionen von EventInit (bubbles, cancelable, composed) und zusätzlich snapTargetBlock und snapTargetInline. Beide sind vom Typ Node | null, Standardwert null.
$snapTargetBlock Node | null null Nur lesbare Instanz-Eigenschaft: das Element, auf das in Block-Richtung eingerastet wird bzw. werden soll.
$snapTargetInline Node | null null Nur lesbare Instanz-Eigenschaft: das Element, auf das in Inline-Richtung eingerastet wird bzw. werden soll.

Rückgabewert

Typ
SnapEvent
Beschreibung
new SnapEvent(type, options) gibt ein neues SnapEvent-Objekt zurück. Im Normalfall erzeugt der Browser die Instanzen selbst und übergibt sie an die Event-Handler.

Beispiele

Aktive Folie eines horizontalen Karussells markieren

// CSS: .carousel { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; }
//      .slide { flex: 0 0 100%; scroll-snap-align: center; }
const carousel = document.querySelector('.carousel');

carousel.addEventListener('scrollsnapchange', (event) => {
  const slide = event.snapTargetInline; // horizontal = Inline-Richtung
  if (!slide) return;

  carousel.querySelectorAll('.slide').forEach((el) =>
    el.classList.toggle('active', el === slide)
  );
  console.log('Aktive Folie:', slide.dataset.index);
});
Aktive Folie: 2

Vorschau während der Wischgeste mit scrollsnapchanging

const list = document.querySelector('.vertical-list'); // scroll-snap-type: y mandatory
const dots = [...document.querySelectorAll('.pager-dot')];

const onSnapChanging = (event) => {
  const target = event.snapTargetBlock; // vertikal = Block-Richtung
  const index = [...list.children].indexOf(target);
  dots.forEach((dot, i) => dot.classList.toggle('preview', i === index));
};

list.addEventListener('scrollsnapchanging', onSnapChanging);

// Alternativ über die on-Eigenschaft:
// list.onscrollsnapchanging = onSnapChanging;

// Später wieder abmelden:
// list.removeEventListener('scrollsnapchanging', onSnapChanging);

Unterstützung prüfen und Event selbst erzeugen

const supported = 'onscrollsnapchange' in window;
console.log('SnapEvent unterstützt:', supported);

if (typeof SnapEvent === 'function') {
  const container = document.querySelector('.carousel');
  const slide = container.firstElementChild;

  container.addEventListener('scrollsnapchange', (e) => {
    console.log(e instanceof SnapEvent, e.snapTargetInline === slide, e.snapTargetBlock);
  });

  // z. B. für Tests: synthetisches Event auslösen
  container.dispatchEvent(
    new SnapEvent('scrollsnapchange', { snapTargetInline: slide })
  );
}
SnapEvent unterstützt: true true true null

// Wichtig · Fallstricke

  • Browserunterstützung: Die API gibt es bislang nur in Chromium-Browsern (Chrome/Edge ab 129). Firefox und Safari unterstützen sie noch nicht. Die Unterstützung lässt sich mit 'onscrollsnapchange' in window prüfen. Als Rückfallebene eignet sich scrollend zusammen mit IntersectionObserver.
  • Block oder Inline: Welche Achse Block und welche Inline ist, hängt von writing-mode ab. Bei normaler horizontaler Schreibweise liefert ein horizontales Karussell sein Ziel in snapTargetInline, eine vertikale Liste in snapTargetBlock. Die jeweils andere Eigenschaft ist dann null.
  • Nur bei Wechsel des Ziels: scrollsnapchange feuert nur, wenn sich das Einrastziel tatsächlich ändert. Rastet der Container nach einem kurzen Scrollen wieder am selben Element ein, kommt kein Event.
  • scrollsnapchanging ist vorläufig: Das gemeldete Ziel kann sich während der Geste mehrfach ändern und muss am Ende nicht das tatsächliche Ziel sein. Aufwendige Arbeit wie Netzwerkanfragen daher erst in scrollsnapchange erledigen.
  • Beide Events lassen sich nicht abbrechen. preventDefault() hat keine Wirkung.
  • Das Ziel kann auch ein Pseudo-Element sein, zum Beispiel ::scroll-marker-Konstrukte in neueren Spezifikationen. Deshalb ist der Typ Node und nicht Element. Vor dem Zugriff auf dataset und Ähnliches sollte man den Typ prüfen.