IntersectionObserver seems to be triggering well before it should in my scenario (yes, I've read quite a few Q&A's here and several guides published around the place).
I'm applying a class after an observed element leaves the viewport. This works in general as you scroll down the page, but on page load, the next element, outside the viewport (could be #box2
or #box3
depending on your browser height) gets the viewed class, before it ever enters the viewport. Here's a codepen.
Can anyone explain why the observed element after the one/s that are in viewport have the viewed class (.js-was-active
) on page load, before they intersect the viewport – and the (presumably obvious) error I've made somewhere?!
Bonus, possibly related, question (while trying to debug the issue above, I shifted the bottom margin of the observer up 50%, but it's triggering as soon as any observed elements enter the viewport, not halfway up, despite rootMargin: '0% 0% -50% 0%'
. Why?
const steps = document.querySelectorAll('.js-iobserve');
const ioConfig = { rootMargin: '0% 0% -50% 0%' };
var isLeaving = false;
observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
var match = '.' + entry.target.getAttribute('id');
if (entry.isIntersecting) {
isLeaving = true;
entry.target.classList.add('js-is-active');
$(match).addClass('js-is-active');
} else if (isLeaving) {
isLeaving = false;
entry.target.classList.remove('js-is-active');
entry.target.classList.add('js-was-active');
$(match).removeClass('js-is-active').addClass('js-was-active');
}
});
}, ioConfig);
$(document).ready(function() {
steps.forEach(step => {
observer.observe(step);
});
});
.js-is-active {
border: 4px dashed red;
}
.js-was-active {
opacity: .5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header class="container-fluid py-4">
<h1 class="text-center">HEADER</h1>
</header>
<div class="container mt-5">
<div class="row">
<div class="col">
<div id="box1" class="d-flex justify-content-center align-items-center bg-info mb-5 js-iobserve" style="height:67vh;">BOX ONE</div>
<div class="my-5 py-5"></div>
<div id="box2" class="d-flex justify-content-center align-items-center bg-danger mb-5 js-iobserve" style="height:67vh;">BOX TWO</div>
<div class="my-5 py-5"></div>
<div id="box3" class="d-flex justify-content-center align-items-center bg-warning mb-5 js-iobserve" style="height:67vh;">BOX THREE</div>
<div class="my-5 py-5"></div>
<div id="box4" class="d-flex justify-content-center align-items-center bg-success mb-5 js-iobserve" style="height:67vh;">BOX FOUR</div>
<div class="my-5 py-5"></div>
<div id="box5" class="d-flex justify-content-center align-items-center bg-info mb-5 js-iobserve" style="height:67vh;">BOX FIVE</div>
<div class="my-5 py-5"></div>
</div>
<div class="col">
<div class="position-sticky" style="top:2rem;">
<h2 class="box1">Box one heading</h2>
<h2 class="box2">Box two heading <br/><small>Why does this have the active class on page load when my rootMargin is -50% on the bottom edge?</small></h2>
<h2 class="box3">Box three heading <br/><small>Why does the io think I've seen this already on page load?</small></h2>
<h2 class="box4">Box four heading</h2>
<h2 class="box5">Box five heading</h2>
</div>
</div>
</div>
</div>