In the following (pretty basic) implementation of intersection observer, I'm noticing that IOS safari is batching the entries very aggressively in a single callback: if I scroll through the six items my observer is watching very quickly, the callback only fires once with six entries, whereas on desktop the callback fires six times, once for each target.
Here is a screen recording demonstrating the problem; I’m expecting to see each target light up as orange when it comes into view, but it appears to “skip” targets, because it batches multiple entries together into a single callback once the scroll ends.
Is this just a safari problem, or is there something I'm doing wrong in my code which could be contributing to this?
Minimum reproducible example:
window.addEventListener('load',function(){
let steps=[...document.querySelectorAll('.step')];
const observerOptions = {
threshold: [0,1],
rootMargin: `0px 0px 0px 0px`,
root: document
};
let observer = new IntersectionObserver((entries) => {
console.log('callback-------------------------')
console.log('batched entries:',entries.length)
let active=null;
for (let entry of entries) {
if(entry.intersectionRatio==1){
active=entry.target;
}
}
console.log('detected fully in view:',active);
if(active){
for(let step of steps){
step.classList.toggle('active',active==step);
}
}
}, observerOptions);
for(let step of steps) observer.observe(step);
})
.step-outer{
height:60svh;
width:100%;
position:relative;
}
.step{
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
box-sizing:border-box;
border-bottom:1px solid red;
transition:background-color 0.3s;
}
.step.active{
background-color: coral;
}
.outer{
margin-top:100px;
margin-bottom:100px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="outer">
<div class="step-outer"><div class="step"></div></div>
<div class="step-outer"><div class="step"></div></div>
<div class="step-outer"><div class="step"></div></div>
<div class="step-outer"><div class="step"></div></div>
<div class="step-outer"><div class="step"></div></div>
<div class="step-outer"><div class="step"></div></div>
</div>
</body>
</html>