'IntersectionObserver callback firing immediately on page load
I'm very new to the IntersectionObserver API, and I've been experimenting with this code:
let target = document.querySelector('.lazy-load');
let options = {
root: null,
rootMargin: '0px',
threshold: 0
}
let observer = new IntersectionObserver(callback, options);
observer.observe(target);
function callback() {
console.log('observer triggered.');
}
This seems to work as it should, and callback() is called whenever .lazy-load element enters the viewport, but callback() also fires once when the page is initially loaded, which triggers `console.log('observer triggered.');
Is there a reason for this callback to be triggered when the page loads? Or is there a mistake in how I'm implementing this?
Edit: Altering the code to the below still fires the callback at page load.
let target = document.querySelector('.lazy-load');
let options = {
root: null,
rootMargin: '0px',
threshold: 0
}
let callback = function(entries, observer) {
entries.forEach(entry => {
console.log('observer triggered.');
});
};
let observer = new IntersectionObserver(callback, options);
observer.observe(target);
Solution 1:[1]
That is the default behaviour. When you instantiate an instance of the IntersectionObserver, the callback will be fired.
It is recommended to guard against this case.
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
entry.target.classList.add('in-viewport');
} else {
entry.target.classList.remove('in-viewport');
}
});
Also I found this article as well as the docs to be very helpful, specifically about the intersectionRatio or isIntersecting properties on the IntersectionObserverEntry.
· https://www.smashingmagazine.com/2018/01/deferring-lazy-loading-intersection-observer-api/
· https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver
· https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry
Solution 2:[2]
as easy as it sounds I was able to fix the issue by
- adding a threshold comparison condition
- adding a slight delay for initialization of observer
const options = {
threshold: 1.0,
};
setTimeout(() => {
observer = new IntersectionObserver(([entry]) => {
console.log("OBSERVER TRIGGERED 1");
if (
entry &&
entry.isIntersecting &&
entry.intersectionRatio >= options.threshold
) {
console.log("OBSERVER TRIGGERED 2");
}
}, options);
observer.observe(observerRef.value);
}, 2000);
I would also suggest temporary changing the background color for observable element to something like:
.observer {
background-color: red;
}
and doing the page refresh. This way your might actually see the red background flashing on your screen hence triggering the event.
Now, before you throw tomatoes at me - in my case - I have a dozen of videos on the webpage. The video HTML elements are not "expanded" right away, because browser needs to download information about the poster images. Hence the page was loaded but vides were still loading one by one.. Adding a slight delay fixed the issue so the browser had time to expand the video contents.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | snewcomer |
| Solution 2 | Alex |
