I'm trying to detect whenever a visitor has scrolled past elements on a page.
I would like to detect scrolling past every .title
element, and add an .active
class to the corresponding anchor menu item. The .active
class should stay on the anchor menu item until scrolling past the next title element.
Here is what I have - adding the .active
class works, but removing it fails.
Anyone able to help?
window.addEventListener("scroll", function () {
document.querySelectorAll('.title').forEach((section) => {
const id = section.getAttribute('id');
if (id) {
if (window.scrollY > (section.offsetTop + section.offsetHeight)) {
document.querySelector(`.menu li a[href="#${id}"]`).classList.add('active');
} else {
document.querySelector(`.menu li a.active`).classList.remove('active');
}
}
});
});
.active {
color: red
}
<ul class="menu">
<li><a href="#one">Link one</a></li>
<li><a href="#two">Link two</a></li>
<li><a href="#three">Link thre</a></li>
<li><a href="#four">Link four</a></li>
<li><a href="#five">Link five</a></li>
</ul>
<div class="container">
<div class="title" id="one">Title one</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus dolor id ullamcorper tempor. Donec ut ullamcorper tellus. Etiam vel rhoncus urna. Aenean augue nulla, congue a orci at, imperdiet vehicula eros. Aenean ornare nibh ut leo faucibus fringilla. Quisque varius ut ipsum egestas feugiat. Mauris id nisl ultrices, consectetur mauris in, consectetur mi. Sed sit amet dolor urna. Nullam nec enim gravida, pulvinar lacus ut, volutpat nibh. Quisque commodo eu tortor ac dictum. Vivamus sodales risus sed blandit vulputate. Proin elit erat, varius non tincidunt ut, semper sed erat. Nulla vehicula vitae nisl nec dignissim. Curabitur viverra risus eu est pellentesque lobortis. Nullam egestas semper convallis.
Ut ac blandit risus, sit amet elementum ex. Donec rhoncus augue eu cursus consequat. Duis a sapien sit amet elit aliquet molestie. Mauris nec ligula viverra, ornare dolor vel, malesuada nisl. Proin gravida dolor justo, sit amet tempus justo consectetur ut. Aenean malesuada iaculis tortor ac varius. Phasellus ultrices purus nisi, eu rutrum felis bibendum id. Phasellus enim dui, ultrices sed massa vel, euismod bibendum eros. Duis quis auctor augue, eget pellentesque velit. In a est at neque dignissim pellentesque et tempus sem. Nulla et leo diam.
</p>
<div class="title" id="two">Title two</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus dolor id ullamcorper tempor. Donec ut ullamcorper tellus. Etiam vel rhoncus urna. Aenean augue nulla, congue a orci at, imperdiet vehicula eros. Aenean ornare nibh ut leo faucibus fringilla. Quisque varius ut ipsum egestas feugiat. Mauris id nisl ultrices, consectetur mauris in, consectetur mi. Sed sit amet dolor urna. Nullam nec enim gravida, pulvinar lacus ut, volutpat nibh. Quisque commodo eu tortor ac dictum. Vivamus sodales risus sed blandit vulputate. Proin elit erat, varius non tincidunt ut, semper sed erat. Nulla vehicula vitae nisl nec dignissim. Curabitur viverra risus eu est pellentesque lobortis. Nullam egestas semper convallis.
Ut ac blandit risus, sit amet elementum ex. Donec rhoncus augue eu cursus consequat. Duis a sapien sit amet elit aliquet molestie. Mauris nec ligula viverra, ornare dolor vel, malesuada nisl. Proin gravida dolor justo, sit amet tempus justo consectetur ut. Aenean malesuada iaculis tortor ac varius. Phasellus ultrices purus nisi, eu rutrum felis bibendum id. Phasellus enim dui, ultrices sed massa vel, euismod bibendum eros. Duis quis auctor augue, eget pellentesque velit. In a est at neque dignissim pellentesque et tempus sem. Nulla et leo diam.
</p>
<div class="title" id="three">Title three</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus dolor id ullamcorper tempor. Donec ut ullamcorper tellus. Etiam vel rhoncus urna. Aenean augue nulla, congue a orci at, imperdiet vehicula eros. Aenean ornare nibh ut leo faucibus fringilla. Quisque varius ut ipsum egestas feugiat. Mauris id nisl ultrices, consectetur mauris in, consectetur mi. Sed sit amet dolor urna. Nullam nec enim gravida, pulvinar lacus ut, volutpat nibh. Quisque commodo eu tortor ac dictum. Vivamus sodales risus sed blandit vulputate. Proin elit erat, varius non tincidunt ut, semper sed erat. Nulla vehicula vitae nisl nec dignissim. Curabitur viverra risus eu est pellentesque lobortis. Nullam egestas semper convallis.
Ut ac blandit risus, sit amet elementum ex. Donec rhoncus augue eu cursus consequat. Duis a sapien sit amet elit aliquet molestie. Mauris nec ligula viverra, ornare dolor vel, malesuada nisl. Proin gravida dolor justo, sit amet tempus justo consectetur ut. Aenean malesuada iaculis tortor ac varius. Phasellus ultrices purus nisi, eu rutrum felis bibendum id. Phasellus enim dui, ultrices sed massa vel, euismod bibendum eros. Duis quis auctor augue, eget pellentesque velit. In a est at neque dignissim pellentesque et tempus sem. Nulla et leo diam.
</p>
<div class="title" id="four">Title four</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus dolor id ullamcorper tempor. Donec ut ullamcorper tellus. Etiam vel rhoncus urna. Aenean augue nulla, congue a orci at, imperdiet vehicula eros. Aenean ornare nibh ut leo faucibus fringilla. Quisque varius ut ipsum egestas feugiat. Mauris id nisl ultrices, consectetur mauris in, consectetur mi. Sed sit amet dolor urna. Nullam nec enim gravida, pulvinar lacus ut, volutpat nibh. Quisque commodo eu tortor ac dictum. Vivamus sodales risus sed blandit vulputate. Proin elit erat, varius non tincidunt ut, semper sed erat. Nulla vehicula vitae nisl nec dignissim. Curabitur viverra risus eu est pellentesque lobortis. Nullam egestas semper convallis.
Ut ac blandit risus, sit amet elementum ex. Donec rhoncus augue eu cursus consequat. Duis a sapien sit amet elit aliquet molestie. Mauris nec ligula viverra, ornare dolor vel, malesuada nisl. Proin gravida dolor justo, sit amet tempus justo consectetur ut. Aenean malesuada iaculis tortor ac varius. Phasellus ultrices purus nisi, eu rutrum felis bibendum id. Phasellus enim dui, ultrices sed massa vel, euismod bibendum eros. Duis quis auctor augue, eget pellentesque velit. In a est at neque dignissim pellentesque et tempus sem. Nulla et leo diam.
</p>
<div class="title" id="five">Title five</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus dolor id ullamcorper tempor. Donec ut ullamcorper tellus. Etiam vel rhoncus urna. Aenean augue nulla, congue a orci at, imperdiet vehicula eros. Aenean ornare nibh ut leo faucibus fringilla. Quisque varius ut ipsum egestas feugiat. Mauris id nisl ultrices, consectetur mauris in, consectetur mi. Sed sit amet dolor urna. Nullam nec enim gravida, pulvinar lacus ut, volutpat nibh. Quisque commodo eu tortor ac dictum. Vivamus sodales risus sed blandit vulputate. Proin elit erat, varius non tincidunt ut, semper sed erat. Nulla vehicula vitae nisl nec dignissim. Curabitur viverra risus eu est pellentesque lobortis. Nullam egestas semper convallis.
Ut ac blandit risus, sit amet elementum ex. Donec rhoncus augue eu cursus consequat. Duis a sapien sit amet elit aliquet molestie. Mauris nec ligula viverra, ornare dolor vel, malesuada nisl. Proin gravida dolor justo, sit amet tempus justo consectetur ut. Aenean malesuada iaculis tortor ac varius. Phasellus ultrices purus nisi, eu rutrum felis bibendum id. Phasellus enim dui, ultrices sed massa vel, euismod bibendum eros. Duis quis auctor augue, eget pellentesque velit. In a est at neque dignissim pellentesque et tempus sem. Nulla et leo diam.
</p>
</div>
Try to add this script i think it should work we need one function to check if an element is in the viewport.
window.addEventListener("scroll", function() {
let activeMenuItem = null;
// Iterate through each .title element
document.querySelectorAll('.title').forEach((section) => {
const id = section.getAttribute('id');
if (id) {
// Check if the user has scrolled past this .title element
if (window.scrollY > (section.offsetTop + section.offsetHeight)) {
// If scrolled past, mark the current .title's corresponding menu item as active
activeMenuItem = document.querySelector(`.menu li a[href="#${id}"]`);
}
}
});
// Remove active class from all menu items
document.querySelectorAll('.menu li a').forEach((menuItem) => {
menuItem.classList.remove('active');
});
// Add active class only to the last identified menu item
if (activeMenuItem) {
activeMenuItem.classList.add('active');
}
});