Signatur
Beschreibung
IntersectionObserverEntry-Objekte werden nicht selbst erzeugt. Der Browser übergibt sie als Array an den Callback eines IntersectionObserver, sobald ein beobachtetes Element einen der festgelegten Schwellenwerte (threshold) überschreitet. Außerdem entsteht direkt nach observe() ein erster Eintrag mit dem Anfangszustand. Einträge lassen sich auch synchron über observer.takeRecords() abholen.
Jeder Eintrag ist eine Momentaufnahme und enthält nur lesbare Eigenschaften:
target: das beobachteteElement.isIntersecting:true, wenn sich das Ziel mit der Wurzel überschneidet (auch bei einer Überschneidung der Fläche 0 an der Kante).intersectionRatio: Anteil des sichtbaren Bereichs am Ziel, zwischen0.0und1.0.boundingClientRect: das Begrenzungsrechteck des Ziels alsDOMRectReadOnly.intersectionRect: das sichtbare Schnittrechteck.rootBounds: das Rechteck der Wurzel inklusiverootMargin. Bei ursprungsübergreifenden iframes kann esnullsein.time: einDOMHighResTimeStampmit dem Zeitpunkt der Überschneidung, relativ zur Entstehungszeit des Dokuments.
Typische Einsatzfälle sind Lazy Loading von Bildern, endloses Scrollen, Messen der Sichtbarkeit von Werbeflächen, Einblende-Animationen beim Scrollen und das Pausieren von Videos außerhalb des Viewports. Anders als Scroll-Handler mit getBoundingClientRect() läuft die Berechnung asynchron und blockiert den Haupt-Thread nicht.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | Element | Nur lesbar: das Element, dessen Überschneidung sich geändert hat. | |
| $isIntersecting Pflicht | boolean | Nur lesbar: true, wenn das Ziel in den Überschneidungszustand übergeht oder sich darin befindet. |
|
| $intersectionRatio Pflicht | number | Nur lesbar: Verhältnis von intersectionRect zu boundingClientRect (0.0 bis 1.0). |
|
| $boundingClientRect Pflicht | DOMRectReadOnly | Nur lesbar: das Begrenzungsrechteck des Zielelements. | |
| $intersectionRect Pflicht | DOMRectReadOnly | Nur lesbar: der sichtbare Schnittbereich von Ziel und Wurzel. | |
| $rootBounds Pflicht | DOMRectReadOnly | null | Nur lesbar: das Rechteck der Wurzel inklusive rootMargin. null bei ursprungsübergreifenden Zielen. |
|
| $time Pflicht | DOMHighResTimeStamp | Nur lesbar: Zeitstempel der Überschneidungsänderung in Millisekunden. |
Rückgabewert
entries-Arrays an den Observer-Callback übergeben oder von takeRecords() zurückgegeben.Beispiele
Lazy Loading von Bildern
// <img data-src="foto.jpg" class="lazy">
const observer = new IntersectionObserver((entries, obs) => {
for (const entry of entries) {
if (!entry.isIntersecting) continue;
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
obs.unobserve(img); // nur einmal laden
}
}, { rootMargin: '200px 0px' });
document.querySelectorAll('img.lazy').forEach((img) => observer.observe(img));
Eigenschaften eines Eintrags auswerten
const box = document.querySelector('#box');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
console.log({
id: entry.target.id,
sichtbar: entry.isIntersecting,
anteil: entry.intersectionRatio.toFixed(2),
hoeheSichtbar: Math.round(entry.intersectionRect.height),
zeit: Math.round(entry.time)
});
});
}, { threshold: [0, 0.5, 1] });
observer.observe(box);
Sichtbarkeit einer Werbefläche messen (≥ 50 %)
const ad = document.querySelector('.ad');
let sichtbarSeit = null;
let gesamt = 0;
const observer = new IntersectionObserver(([entry]) => {
if (entry.intersectionRatio >= 0.5) {
sichtbarSeit ??= entry.time;
} else if (sichtbarSeit !== null) {
gesamt += entry.time - sichtbarSeit;
sichtbarSeit = null;
console.log(`Sichtbar insgesamt: ${Math.round(gesamt)} ms`);
}
}, { threshold: [0, 0.5] });
observer.observe(ad);
Scroll-Richtung über boundingClientRect erkennen
let letztesY = 0;
const observer = new IntersectionObserver(([entry]) => {
const y = entry.boundingClientRect.y;
const richtung = y < letztesY ? 'nach unten' : 'nach oben';
letztesY = y;
if (entry.isIntersecting) console.log(`Abschnitt betreten, Scrollrichtung: ${richtung}`);
});
observer.observe(document.querySelector('section'));
// Wichtig · Fallstricke
- Erster Aufruf: Direkt nach
observe()wird der Callback einmal mit dem Anfangszustand aufgerufen, auch wenn das Element nicht sichtbar ist. Deshalb immerisIntersectingprüfen. isIntersectingstattintersectionRatio > 0: Ein Element, das die Wurzel nur an der Kante berührt, hat den Anteil0, gilt aber trotzdem als überschneidend. Auch Elemente ohne Fläche (Höhe 0) haben immer den Anteil 0.- Keine Echtzeitwerte: Der Eintrag ist eine Momentaufnahme. Die Benachrichtigung kommt asynchron und nur, wenn ein Schwellenwert überschritten wird, nicht bei jedem gescrollten Pixel. Für pixelgenaue Animationen ist das ungeeignet.
rootBoundskannnullsein: Das passiert, wenn das Ziel in einem ursprungsübergreifenden iframe liegt und keine explizite Wurzel angegeben ist. Aus Datenschutzgründen wird dann auchrootMarginignoriert.- Mehrere Einträge: Das
entries-Array kann mehrere Einträge für dasselbe Ziel enthalten. Ist nur der aktuelle Zustand wichtig, zählt der letzte Eintrag. - Browser-Kompatibilität: Wird von allen modernen Browsern unterstützt (Chrome 58+, Firefox 55+, Safari 12.1+).
isIntersectingkam in manchen Browsern später dazu. Für sehr alte Umgebungen gibt es ein Polyfill. - Die Eigenschaften
isVisibleundtrackVisibilitygehören zu Intersection Observer v2 und gibt es nur in Chromium-Browsern.