I would like to detect a user's scroll and make an element fixed to top by adding a class when it's reached by scolling and below. The class should be removed when the user is scrolling above the element. I can't use the css property position: sticky.
I'm currently using IntersectionObserver but it's adding the fixed class even when the element is not in view because of !entry.isIntersecting
.
Is there a way to get around that? Is there another or better way to add a fixed class only when scrolled below an element?
const watcher = document.querySelector('.watcher');
const evu = document.getElementById('box');
const createObserver = () => {
const options = {
root: null,
trackVisibility: true,
delay: 100,
threshold: [.9]
}
const handler = (entries) => {
entries.forEach((entry) => {
entry.target.nextElementSibling.classList.toggle('fixed', !entry.isIntersecting);
})
}
if ('IntersectionObserver' in window) {
const observer = new window.IntersectionObserver(handler, options);
observer.observe(watcher);
}
};
There are definitely a few ways to do this, but using your code the simplest is to just add a check to see if the current scroll position window.scrollY
is greater than or equal to the y position of your element entry.boundingClientRect.top
.
const watcher = document.querySelector('.watcher');
const evu = document.getElementById('box');
const createObserver = () => {
const options = {
root: null,
trackVisibility: true,
delay: 100,
threshold: [.9]
}
const handler = (entries) => {
entries.forEach((entry) => {
entry.target.nextElementSibling.classList.toggle('fixed', !entry.isIntersecting && window.scrollY >= entry.boundingClientRect.top);
})
}
if ('IntersectionObserver' in window) {
const observer = new window.IntersectionObserver(handler, options);
observer.observe(watcher);
}
};
window.addEventListener('load', () => {
createObserver();
}, false);
window.addEventListener('scroll', () => {
createObserver();
}, {
passive: true
});
.fixed {
position: fixed;
top: 0;
border: 1px solid red;
}
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<div class="watcher"></div>
<div id="element">
Add fixed class only when I'm intersected or below.
Remove class when above element.
</div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
You definitely could do this without an intersection observer by attaching an event listener to the scroll event of the window
object and checking if the window's y position is greater than or equal to your specific element's top position.