I'm very new to JavaScript so apologies if I'm lacking clarity in any of my description.
I've built a small website that has a java-script generated menu and I'm just wanting to add functionality to highlight a section (and make 'active') in the menu when scrolled to. I've put together the following, which isn't throwing any errors in the console, so I'm unsure what I've missed:
const sectionHead = document.querySelectorAll('h2');
const sections = document.querySelectorAll('section');
const nav = document.querySelector('nav');
// build the nav
function navMenu(){
for(let section of sectionHead){
let listItem = document.createElement("li");
listItem.innerHTML = section.textContent;
nav.appendChild(listItem);
listItem.classList.add('menu__link');
listItem.addEventListener("click", ()=>{
section.scrollIntoView({behavior: "smooth"});
});
};
}
navMenu();
const nav_items = document.querySelectorAll('.menu__link')
window.addEventListener("scroll", () => {
let current = "";
sections.forEach((section) => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (pageYOffset >= sectionTop - sectionHeight / 3) {
current = section.getAttribute("id");
}
});
//set section as active
nav_items.forEach((li) => {
li.classList.remove("your-active-class");
section.classList.remove("your-active-class");
if (section.classList.contains(current)) {
section.classList.add("your-active-class");
//console.log (li.classList);
}
});
});
The 'your-active-class' class has some custom CSS setup so it will just change visibility in the menu.
Any help is really appreciated
This is how you would observe whether a DOM Element is within view, and apply/remove a classname to it. If you look at your inspector, you'll see the 'active' class being added/removed when they enter and exit view.
window.addEventListener("load", function() { //Query objects on document load const sections = document.querySelectorAll("section") console.log(`We have ${sections.length} sections`) // Create options for Observer: const options = { rootMargin: '100px 0px', threshold: [0.25, 0, 0.25, 0] } // Create instance of IO: let observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.intersectionRatio > 0) { entry.target.classList.add('active') } else { entry.target.classList.remove('active') } }) }, options) // Iterate over each queried el, and add observer: sections.forEach(section => { observer.observe(section) }) })
section { background-color: red; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 6rem auto; transition: all 300ms ease-in-out; }.active { background-color: rgba(0,255,0,0.3); transition: all 300ms ease-in-out; }
<section><div>This is the first section</div></section> <section><div>This is the second</div></section> <section><div>This is the third</div></section>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.