Mit IntersectionObservers können Sie feststellen, wann ein beobachtetes Element in den Darstellungsbereich des Browsers ein- oder aus ihm austritt.
Angenommen, Sie möchten erfassen, wann ein Element in Ihrem DOM in den sichtbaren Darstellungsbereich gelangt. Das kann sinnvoll sein, wenn Sie Bilder erst bei Bedarf laden möchten oder wissen müssen, ob der Nutzer sich einen bestimmten Anzeigenbanner ansieht. Dazu können Sie das Scroll-Ereignis einbinden oder einen periodischen Timer verwenden und getBoundingClientRect()
für das Element aufrufen.
Dieser Ansatz ist jedoch sehr langsam, da bei jedem Aufruf von getBoundingClientRect()
der Browser gezwungen wird, das Layout der gesamten Seite neu zu berechnen. Das führt zu erheblichen Rucklern auf Ihrer Website. Es wird fast unmöglich, wenn Sie wissen, dass Ihre Website in einem iFrame geladen wird und Sie wissen möchten, wann der Nutzer ein Element sehen kann. Das Single Origin Model und der Browser verhindern, dass Sie auf Daten der Webseite zugreifen, die den iFrame enthält. Dies ist ein häufiges Problem bei Anzeigen, die häufig über iFrames geladen werden.
IntersectionObserver
wurde entwickelt, um diesen Sichtbarkeitstest effizienter zu gestalten, und ist in allen modernen Browsern verfügbar. Mit IntersectionObserver
können Sie feststellen, wann ein beobachtetes Element in den Viewport des Browsers eintritt oder ihn verlässt.

IntersectionObserver
erstellen
Die API ist relativ klein und lässt sich am besten anhand eines Beispiels beschreiben:
const io = new IntersectionObserver(entries => {
console.log(entries);
}, {
/* Using default options. Details below */
});
// Start observing an element
io.observe(element);
// Stop observing an element
// io.unobserve(element);
// Disable entire IntersectionObserver
// io.disconnect();
Wenn Sie die Standardoptionen für IntersectionObserver
verwenden, wird Ihr Callback sowohl aufgerufen, wenn das Element teilweise in den sichtbaren Bereich gelangt, als auch, wenn es den sichtbaren Bereich vollständig verlässt.
Wenn Sie mehrere Elemente beobachten müssen, ist es sowohl möglich als auch ratsam, mehrere Elemente mit derselben IntersectionObserver
-Instanz zu beobachten, indem Sie observe()
mehrmals aufrufen.
An Ihren Callback wird ein entries
-Parameter übergeben, der ein Array von IntersectionObserverEntry
-Objekten ist. Jedes dieser Objekte enthält aktualisierte Schnittmengendaten für eines Ihrer beobachteten Elemente.
🔽[IntersectionObserverEntry]
time: 3893.92
🔽rootBounds: ClientRect
bottom: 920
height: 1024
left: 0
right: 1024
top: 0
width: 920
🔽boundingClientRect: ClientRect
// ...
🔽intersectionRect: ClientRect
// ...
intersectionRatio: 0.54
🔽target: div#observee
// ...
rootBounds
ist das Ergebnis des Aufrufs von getBoundingClientRect()
für das Stammelement, das standardmäßig der Darstellungsbereich ist. boundingClientRect
ist das Ergebnis von getBoundingClientRect()
, das für das beobachtete Element aufgerufen wird. intersectionRect
ist der Schnittpunkt dieser beiden Rechtecke und gibt effektiv an, welcher Teil des beobachteten Elements sichtbar ist. intersectionRatio
ist eng damit verbunden und gibt an, wie viel des Elements sichtbar ist. Mit diesen Informationen können Sie jetzt Funktionen wie das Just-in-Time-Laden von Assets implementieren, bevor sie auf dem Bildschirm sichtbar werden. Effizient.

IntersectionObserver
liefern ihre Daten asynchron und Ihr Callback-Code wird im Hauptthread ausgeführt. Außerdem wird in der Spezifikation festgelegt, dass IntersectionObserver
-Implementierungen requestIdleCallback()
verwenden sollten. Das bedeutet, dass der Aufruf Ihres bereitgestellten Callbacks eine niedrige Priorität hat und vom Browser in der Leerlaufzeit erfolgt. Das ist eine bewusste Designentscheidung.
Scrollende div-Elemente
Ich bin kein großer Fan des Scrollens innerhalb eines Elements, aber ich bin nicht hier, um zu urteilen, und IntersectionObserver
auch nicht. Das options
-Objekt akzeptiert die Option root
, mit der Sie eine Alternative zum Viewport als Stamm definieren können. root
muss ein übergeordnetes Element aller beobachteten Elemente sein.
Alles überschneiden!
Nein! Schlechter Entwickler! Das ist keine schonende Nutzung der CPU-Zyklen Ihrer Nutzer. Nehmen wir als Beispiel einen unendlichen Scroller: In diesem Fall ist es auf jeden Fall ratsam, dem DOM Sentinel-Elemente hinzuzufügen und diese zu beobachten (und wiederzuverwenden!). Sie sollten einen Sentinel in der Nähe des letzten Elements im unendlichen Scroller hinzufügen. Wenn der Sentinel in den sichtbaren Bereich kommt, können Sie mit dem Callback Daten laden, die nächsten Elemente erstellen, sie an das DOM anhängen und den Sentinel entsprechend neu positionieren. Wenn Sie den Sentinel ordnungsgemäß wiederverwenden, ist kein zusätzlicher Aufruf von observe()
erforderlich. Die IntersectionObserver
funktioniert weiterhin.

Weitere Updates
Wie bereits erwähnt, wird der Callback einmal ausgelöst, wenn das beobachtete Element teilweise im Anzeigebereich zu sehen ist, und ein weiteres Mal, wenn es den Anzeigebereich verlässt. So erhalten Sie mit IntersectionObserver
eine Antwort auf die Frage „Ist Element X im Blickfeld?“. In einigen Anwendungsfällen reicht das jedoch möglicherweise nicht aus.
Hier kommt die Option threshold
ins Spiel. Damit können Sie ein Array von intersectionRatio
-Schwellenwerten definieren. Ihr Callback wird jedes Mal aufgerufen, wenn intersectionRatio
einen dieser Werte überschreitet. Der Standardwert für threshold
ist [0]
. Das erklärt das Standardverhalten. Wenn wir threshold
in [0, 0.25, 0.5, 0.75, 1]
ändern, werden wir jedes Mal benachrichtigt, wenn ein weiteres Viertel des Elements sichtbar wird:

Gibt es noch andere Optionen?
Derzeit gibt es nur eine zusätzliche Option zu den oben aufgeführten. Mit rootMargin
können Sie die Ränder für den Stamm angeben. So können Sie den Bereich, der für Überschneidungen verwendet wird, vergrößern oder verkleinern. Diese Ränder werden mit einem CSS-String angegeben, z. B. "10px 20px 30px 40px"
, der den oberen, rechten, unteren und linken Rand angibt. Zusammenfassend bietet die IntersectionObserver
-Optionsstruktur die folgenden Optionen:
new IntersectionObserver(entries => {/* … */}, {
// The root to use for intersection.
// If not provided, use the top-level document's viewport.
root: null,
// Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
// If an explicit root element is specified, components may be percentages of the
// root element size. If no explicit root element is specified, using a
// percentage is an error.
rootMargin: "0px",
// Threshold(s) at which to trigger callback, specified as a ratio, or list of
// ratios, of (visible area / total area) of the observed element (hence all
// entries must be in the range [0, 1]). Callback will be invoked when the
// visible ratio of the observed element crosses a threshold in the list.
threshold: [0],
});
<iframe>
Magie
IntersectionObserver
s wurden speziell für Werbedienste und Social-Media-Widgets entwickelt, die häufig <iframe>
-Elemente verwenden und davon profitieren könnten, wenn sie wissen, ob sie sichtbar sind. Wenn ein <iframe>
eines seiner Elemente beobachtet, wird der Callback sowohl beim Scrollen des <iframe>
als auch beim Scrollen des Fensters , das das <iframe>
enthält, zu den entsprechenden Zeiten ausgelöst. Im letzteren Fall wird rootBounds
jedoch auf null
gesetzt, um zu verhindern, dass Daten über verschiedene Ursprünge hinweg weitergegeben werden.
Worum geht es bei IntersectionObserver
nicht?
IntersectionObserver
ist bewusst weder pixelgenau noch latenzarm. Wenn Sie sie für scrollabhängige Animationen verwenden, wird das wahrscheinlich nicht funktionieren, da die Daten streng genommen veraltet sind, wenn Sie sie verwenden. Weitere Informationen zu den ursprünglichen Anwendungsfällen für IntersectionObserver
finden Sie in der Kurzbeschreibung.
Wie viel Arbeit kann ich im Rückruf erledigen?
Kurz und bündig: Wenn Sie zu viel Zeit im Callback verbringen, wird Ihre App verzögert. Es gelten alle gängigen Praktiken.
Gehe voran und schneide deine Elemente
Die Browserunterstützung für IntersectionObserver
ist gut, da sie in allen modernen Browsern verfügbar ist. Bei Bedarf kann in älteren Browsern ein Polyfill verwendet werden, das im Repository von WICG verfügbar ist. Mit diesem Polyfill erhalten Sie natürlich nicht die Leistungssteigerungen, die eine native Implementierung bietet.
Sie können IntersectionObserver
jetzt verwenden. Erzählen Sie uns, was Sie sich überlegt haben.