My understanding is that IntersectionObserver v2 in Chrome should report whether an iframe is truly visible and nothing is covering it. So I created a simple test case:
main.html
<!doctype html>
<html><head></head>
<body>
<div style="background-color: green; width: 200px; height: 200px;
position: absolute;">Test</div>
<iframe style="width:100px; height: 100px; border: 0;" scrolling="no" src="https://other.domain/inner.html"></iframe>
</body></html>
And here is other.domain/inner.html:
<body style="margin:0">
<div id="test" style="width:100px; height:100px; background-color:
purple;"></div>
<script>
const cb = (entries) => {
entries.forEach((entry) => {
console.log(
'isIntersecting:',
entry.isIntersecting,
'isVisible:',
entry.isVisible
);
});
};
const observer = new IntersectionObserver(cb, {
threshold: 0.0,
root: null,
trackVisibility: true,
delay: 100,
});
setTimeout(() => {
const el = document.getElementById('test');
observer.observe(el);
}, 100);
</script>
</body>
The setTimeout is to simulate a script taking a while to load into the browser.
If the setTimeout is not present I get on page load inconsistent results.
Some times I just see:
isIntersecting: true isVisible: false
Which is what I would expect.
But most of the time I'll see two lines:
isIntersecting: true isVisible: true
isIntersecting: true isVisible: false
And I don't understand where that first true/true line is coming from. I'm guessing the second line is after the 100ms delay, but why should it ever return isVisible true?
But when I add in the timeout. All I see is the true/true line and I can't get the other line to show up at all:
isIntersecting: true isVisible: true
That's obviously not right. The iframe is being covered by a big green square.
Interestingly if I put the iframe further down the page and scroll it into the viewport it behaves exactly as I would expect. It seems to happen only on initial load or refresh.
Any help and understanding you can provide would be much appreciated.