I'm trying to ditch jQuery from my upcoming projects. I found a way to create a sticky nav on scroll with pure Vanilla JS, and wanted the links on my navigation to change their active state as they reach the corresponding sections.
Below is the working solution I came up with, but I'm sure that the code can be improved to work programmatically without having to select and create conditions for each element.
I'm also using a lot of different selectors, and I'm pretty sure there must be a way to improve that, maybe using querySelectorAll
and adding an eventListener
in a forEach
loop, but I can't get that to work either. Thanks for your help!
// select links
const allLinks = document.querySelectorAll('header nav ul li');
const linkTop = document.querySelector('#linkTop');
const linkAbout = document.querySelector('#linkAbout');
const linkServices = document.querySelector('#linkServices');
const linkClients = document.querySelector('#linkClients');
const linkContact = document.querySelector('#linkContact');
// select sections
const sectionTop = document.querySelector('#top');
const sectionAbout = document.querySelector('#about');
const sectionServices = document.querySelector('#services');
const sectionClients = document.querySelector('#clients');
const sectionContact = document.querySelector('#contact');
function changeLinkState() {
// home
if (window.scrollY >= sectionTop.offsetTop) {
allLinks.forEach(link => {
link.classList.remove('active');
});
linkTop.classList.add('active');
}
// about
if (window.scrollY >= sectionAbout.offsetTop) {
allLinks.forEach(link => {
link.classList.remove('active');
});
linkAbout.classList.add('active');
}
// services
if (window.scrollY >= sectionServices.offsetTop) {
allLinks.forEach(link => {
link.classList.remove('active');
});
linkServices.classList.add('active');
}
clients
if (window.scrollY >= sectionClients.offsetTop) {
allLinks.forEach(link => {
link.classList.remove('active');
});
linkClients.classList.add('active');
}
contact
if (window.scrollY >= sectionContact.offsetTop) {
allLinks.forEach(link => {
link.classList.remove('active');
});
linkContact.classList.add('active');
}
}
window.addEventListener('scroll', changeLinkState);
<nav>
<ul>
<li id="linkTop">
<a href="#top">Home</a>
</li>
<li id="linkAbout">
<a href="#about">About Us</a>
</li>
<li id="linkServices">
<a href="#services">Services</a>
</li>
<li id="linkClients">
<a href="#clients">Clients</a>
</li>
<li id="linkContact">
<a href="#contact">Contact</a>
</li>
</ul>
</nav>
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…