I have written a jQuery function that changes the css value of a nav menu item based on if its reference section is viewable in the window.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll <= 590) {
$("#menu-item-25 a").addClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 591 && scroll <= 1380) {
$("#menu-item-26 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 1381 && scroll <= 2545) {
$("#menu-item-22 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 2546 && scroll <= 2969) {
$("#menu-item-23 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 2970) {
$("#menu-item-24 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
}
});
It looks awfully ugly. Is there a better way to achieve this goal?
All the previous answers will work just fine, because you have multiple ways to make this better just making some changes to your CSS selectors, but if you will do all this calculations in the scroll event, you should read this John Resign Post about how to deal with scroll event, specially this part:
So, in your case I would go like this:
HTML:
Jquery:
You shouldn’t be accessing a common group of elements using their ID’s –
Example
1 – Remove classes from all
<a>
‘s in.menu
2 – Display the one you want
You should also consider caching the DOM selectors –
var menuItem22 = $("#menu-item-22 a")
and then access it like:
$(menuItem22).addClass('red')
This will prevent you from accessing the DOM each time you want to perform an op on the element. This is not absolutely necessary in your case but it’s a good trick to keep in mind
How about this?
http://pastebin.com/SrtE3yxS
});
You could use a function to do the ever same thing..
});
I’d like to add another approach (my personal favorite)
Use
setTimeout()
for scroll event handlingUse
getBoundingClientRect()
for detecting elements in viewhttps://codepen.io/oriadam/pen/NLMqjN