IntersectionObserver for multiple targets

Basically I want to have a fixed button for a quick navigate at top of the page but I don't want to display the button for first few top elements. I have this code pen with an example of what I tried but it works partially. Sometimes the Up button disappear even if I am scrolling in the divs where I want to display the button. https://codepen.io/Andreica289/pen/qBLZvRg I appreciate each insight on this or any other approach to create a fixed button after a certain amount of page has been scrolled.
3 Replies
Joao
Joao16mo ago
The issue is you're observing every div, so the callback function fires multiple times as you scroll through each .intersect element. It goes from visible to not visible constantly. It should start as hidden, then choose one element where it will trigger the callback to visible. Then, when you scroll back up towards the top and intersect with that same element it will hide again.
Andreik289
Andreik289OP16mo ago
Ok but if I modify the function to get out from callback when at least one element is intersecting why it doesn't work? This should prevent the callback to bounce between multiple fires and show the button when at least one .intersect element is found but instead if a div occupy the entire viewport and the start and end of div is out of viewport, the interesect it's simply false. Am I right?
function observerCallback(entries, observer) {
var intersect = false;
for(entry of entries) {
if(entry.isIntersecting) {
intersect = true;
break;
}
};
if (intersect) {
target.classList.add('visible');
} else {
target.classList.remove('visible');
}
};
function observerCallback(entries, observer) {
var intersect = false;
for(entry of entries) {
if(entry.isIntersecting) {
intersect = true;
break;
}
};
if (intersect) {
target.classList.add('visible');
} else {
target.classList.remove('visible');
}
};
Joao
Joao15mo ago
Ah, you also need to account for the fact that the callback fires when the target element comes into view and then again once it leaves. Remember that it checks for all sides of the rectangle that make up the element, so it fires once when it comes into view and again when it leaves out of view.
const target = document.querySelector(".nav-button");

function observerCallback([entry], observer) {
if (entry.isIntersecting) {
target.classList.toggle("visible");
}
}

const observer = new IntersectionObserver(observerCallback);

observer.observe(document.querySelector(".intersect"));
const target = document.querySelector(".nav-button");

function observerCallback([entry], observer) {
if (entry.isIntersecting) {
target.classList.toggle("visible");
}
}

const observer = new IntersectionObserver(observerCallback);

observer.observe(document.querySelector(".intersect"));
Note that the isIntersecting property returns "true" when the element comes into view for the first time and "false" when it goes out of view. On an unrelated note: prefer the use of const and let when declaring variables. var is deprecated at this point and shouldn't be used, due to some undesired behaviors around variable scope.
Want results from more Discord servers?
Add your server