I started off with a situation where I wanted to observe an element on my page, let's call it "trigger". It is usually always visible upon page load (above the fold).
As we scroll down, if "trigger" is no longer visible, I want to apply a CSS class to another element.
Here is my code for doing so and it works:
const trigger = document.getElementById('trigger')
const otherElement = document.getElementById('some-other-element')
const intersectionObserver = new IntersectionObserver(
([entry]) => {
if (entry.intersectionRatio === 0) {
otherElement.classList.add('special-class')
} else if (entry.intersectionRatio === 1) {
otherElement.classList.remove('special-class')
}
},
{
threshold: [0, 1],
},
)
intersectionObserver.observe(trigger)
Upon testing this, I realized that users can have smaller devices in which case the bottom edge of the device is actually above where the "trigger" sits so on page load, the "trigger" is actually not visible. Therefore, my "special-class" is automatically applied which is not what I want to have happen.
I thought of a solution to this issue which would be to observe two elements: my trigger and another element like a nav bar or a header which will always be at the top of the page and only if both elements have been scrolled past do I apply my "special-class". However, I could not figure out how to get IntersectionObserver to observe both elements and how my code would change accordingly.
To add the "special-class" if the (header or nav) and otherElement are visible, you can use this code:
const trigger = document.getElementById("trigger");
const header = document.getElementById("header");
const otherElement = document.getElementById("some-other-element");
let triggerVisible = true;
let headerVisible = true;
const updateClass = () => {
if (!triggerVisible && !headerVisible) {
otherElement.classList.add("special-class");
} else {
otherElement.classList.remove("special-class");
}
};
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.target === trigger) {
triggerVisible = entry.isIntersecting;
} else if (entry.target === header) {
headerVisible = entry.isIntersecting;
}
}
updateClass();
}, {
threshold: 0
}
);
observer.observe(trigger);
observer.observe(header);
body {
height: 200vh;
}
#trigger {
margin-top: 50vh;
}
#some-other-element {
position: fixed;
right: 0;
top: 0;
padding: 0 10em 0;
}
div.special-class {
background-color: red;
}
<header id="header">Header</header>
<div id="trigger">Trigger</div>
<div id="some-other-element">Other</div>