Trying to understand a quirk in intersectionObserver API.
If an observed element is partially on screen but has not met the threshold defined in the options I would expect the call back not to fire, but it does. Trying to understand why or how to prevent it on page load.
function handleIntersect(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
// Should only fire at >= 0.8
console.log(entry, entry.intersectionRatio);
entry.target.classList.add('play');
}
});
}
function createObserver(element) {
let observer;
const options = {
threshold: [0.8]
};
observer = new IntersectionObserver(handleIntersect, options);
observer.observe(element);
}
const waypoints = document.querySelectorAll('.section');
waypoints.forEach(waypoint => {
createObserver(waypoint);
});
Reduced test case: https://codepen.io/WithAnEs/pen/gxZPMK
Notice how the first 2 sections are animated in even though the second section does not meet the 0.8 threshold (console log). The first inclination is to add an intersectionRatio > 0.8
check, but this is a duplicate effort. Also, the ratio reporting is delayed so could be inaccurate enough not to pass this check.
isIntersecting
doesn't depend on thresholds. It istrue
, iftarget
element touches or intersectsroot
element. So it's alwaystrue
ifintersectionRatio > 0
.Generally,
callback
is called when conditionintersectionRatio >= your_threshold
is changed. Therefore it can be called with anyintersectionRatio
value.Moreover, it's always called initially.
Also pay attention that
0.8
is just your desired threshold, butobserver.thresholds[0]
is actual. Without going into details, they could be different a bit, e.g. in Chrome.