Click here to Skip to main content
15,867,488 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I want to make the links in my navbar have an active class when you scroll into the corresponding section.

The code below was working just fine until I implemented a smooth scroll/parallax library which removes the scroll event.

Here's a codepen. If you uncomment the locomotive portion in the JS, the code no longer works. How can I make it work?

Here's a snippet of the code:

JavaScript
const sections = document.querySelectorAll("section");
const navLinks = document.querySelectorAll("nav a");

window.addEventListener("scroll", function () {
  let navbar = document.querySelector("nav");
  let current = "";
  sections.forEach(function (section) {
    const sectionTop = section.offsetTop;
    const sectionHeight = section.clientHeight;
    if (scrollY >= sectionTop - sectionHeight / 3) {
      current = `#${section.getAttribute("id")}`;
    }
    navLinks.forEach(function (each) {
      // add/remove active class
      each.classList.remove("nav-active");
      if (each.getAttribute("href") == current) {
        each.classList.add("nav-active");
      }
    });
  });
});


What I have tried:

I tried making the code work using the wheel event, tried seeing if there was anything similar to scrollY for wheel events but I couldn't find anything.

Any ideas on how I could implement this feature? It can be different from the implementation I had before
Posted
Updated 15-Sep-21 23:47pm
Comments
Richard Deeming 16-Sep-21 3:48am    
Looks like you've already got your answer on StackOverflow:
javascript - Make navbar link active on wheel event rather than scroll? - Stack Overflow[^]
Fernanda Azevedo 16-Sep-21 5:00am    
No, the answer there doesn't answer my question. As I said, I've already tried wheel event but it doesn't work because I was using "ScrollY" and that doesn't exist in wheel events

1 solution

Try using an IntersectionObserver instead:
JavaScript
const navLinks = document.querySelectorAll("nav a");

const updateNav = (entries, observer) => {
    const matchingIds = entries.filter(e => e.isIntersecting).map(e => `#${e.target.id}`);
    
    if (matchingIds.length !== 0) {
        const current = matchingIds[0];
        navLinks.forEach(function(link) {
            link.classList.remove("nav-active");
            if (link.getAttribute("href") == current) {
                link.classList.add("nav-active");
            }
        });
    }
};

const options = {
    root: null,
    rootMargin: "0px",
    threshold: 0.66
}

const observer = new IntersectionObserver(updateNav, options);
document.querySelectorAll("*[data-scroll-section]").forEach(el => observer.observe(el));
Intersection Observer API - Web APIs | MDN[^]
Demo[^]
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900