Start · Sprachen · JavaScript · Referenz · IntersectionObserver.root

IntersectionObserver.root

Eigenschaft

Nur lesbare Eigenschaft, die das <code>Element</code> oder <code>Document</code> liefert, dessen Grenzen als Viewport für die Schnittpunkt-Berechnung dienen – oder <code>null</code> für den Browser-Viewport.

seit JavaScript Baseline: alle modernen Browser (seit 2019) Kategorie: webapi

Signatur

IntersectionObserver.root

Beschreibung

Die Eigenschaft root eines IntersectionObserver gibt an, gegen welchen Bereich die Sichtbarkeit der beobachteten Zielelemente berechnet wird. Der Wert entspricht der Option root, die beim Erzeugen des Observers im Konstruktor übergeben wurde. Die Eigenschaft ist nur lesbar. Um den Root zu ändern, muss man einen neuen Observer erzeugen.

Ist root gleich null, spricht man von einem impliziten Root: Berechnet wird dann gegen den Viewport des obersten Dokuments. Das ist der häufigste Fall, etwa beim Lazy Loading von Bildern oder bei Scroll-Animationen. Wird dagegen ein Element angegeben, z. B. ein scrollbarer Container, zählt nur dessen Clip-Bereich (Inhaltsbereich abzüglich Scrollbalken), erweitert oder verkleinert um rootMargin.

Seit einer Erweiterung der Spezifikation darf root auch ein Document sein. Das ist vor allem in iframes nützlich: Übergibt man dort das eigene document, wird gegen den Viewport des iframes statt gegen den des obersten Fensters gemessen. Zudem darf rootMargin dann auch bei ursprungsübergreifenden (cross-origin) iframes angewendet werden.

In der Praxis liest man root vor allem aus, wenn ein Observer in mehreren Kontexten wiederverwendet wird oder wenn man in Debug- und Hilfsfunktionen herausfinden will, auf welchen Container sich die gemeldeten rootBounds beziehen.

Rückgabewert

Typ
Element | Document | null
Beschreibung
Das Element oder Dokument, das als Root dient, oder null, wenn der Viewport des obersten Dokuments verwendet wird.

Beispiele

Impliziter Root (Browser-Viewport)

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) console.log('Sichtbar:', entry.target.id);
  });
});

console.log(observer.root); // kein root übergeben
console.log(observer.root === null ? 'Viewport des Top-Level-Dokuments' : 'eigener Root');
null Viewport des Top-Level-Dokuments

Scroll-Container als Root für Lazy Loading

const container = document.querySelector('#galerie');

const lazyObserver = new IntersectionObserver((entries, obs) => {
  entries.forEach((entry) => {
    if (!entry.isIntersecting) return;
    const img = entry.target;
    img.src = img.dataset.src;
    obs.unobserve(img);
  });
}, { root: container, rootMargin: '200px 0px' });

container.querySelectorAll('img[data-src]').forEach((img) => lazyObserver.observe(img));

console.log(lazyObserver.root === container);
console.log(lazyObserver.root.id);
true galerie

Document als Root innerhalb eines iframes

// Läuft im iframe: gegen den Viewport des iframes messen
const observer = new IntersectionObserver((entries) => {
  entries.forEach((e) => console.log(e.target.id, e.intersectionRatio.toFixed(2)));
}, { root: document, rootMargin: '50px' });

console.log(observer.root instanceof Document);
observer.observe(document.querySelector('#banner'));
true

Root in einer Hilfsfunktion auswerten

const describeRoot = (observer) => {
  const { root } = observer;
  if (root === null) return 'Viewport';
  if (root instanceof Document) return 'Dokument';
  return `Element <${root.tagName.toLowerCase()}${root.id ? '#' + root.id : ''}>`;
};

const list = document.createElement('div');
list.id = 'liste';
document.body.append(list);

console.log(describeRoot(new IntersectionObserver(() => {})));
console.log(describeRoot(new IntersectionObserver(() => {}, { root: list })));
Viewport Element <div#liste>

// Wichtig · Fallstricke

  • Nur lesbar: Eine Zuweisung wie observer.root = el wird ignoriert bzw. wirft im Strict Mode einen TypeError. Um den Root zu wechseln, erzeugt man einen neuen Observer.
  • Zielelemente müssen Nachfahren sein: Ist root ein Element, werden nur Ziele korrekt ausgewertet, die im DOM-Baum unterhalb dieses Elements liegen. Andernfalls ist isIntersecting immer false.
  • Overflow erforderlich: Ein Element-Root schneidet nur dann sinnvoll ab, wenn es einen eigenen Clip-Bereich hat (z. B. overflow: auto oder hidden). Ohne Clipping verhält es sich oft anders als erwartet.
  • Document als Root wird erst seit Chrome/Edge 81, Firefox 76 und Safari 14.1 unterstützt. Ältere Browser werfen beim Konstruktor einen TypeError. null und Elemente funktionieren überall.
  • Bei implizitem Root in cross-origin iframes ist entry.rootBounds aus Datenschutzgründen null, und rootMargin wird ignoriert.
  • Der Observer hält eine Referenz auf den Root. Wird der Container entfernt, sollte man disconnect() aufrufen, damit keine Speicherlecks entstehen.