Reputation: 533
I currently have a sticky scroll navigation that changes the active class as it passes each section on the page. It is a little buggy though...
heres my jquery code:
var s = $("#page-nav"),
pos = s.position();
$(window).scroll(function() {
var windowpos = $(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("stick");
$('.main').css('margin-top', '60px');
} else {
s.removeClass("stick");
$('.main').removeAttr('style');
}
});
$(window).scroll(function() {
var y = $(this).scrollTop();
$('.linky').each(function (event) {
id = $(this).attr('href');
if (y >= $(id).offset().top) {
$('.linky').not(this).removeClass('active');
$(this).addClass('active');
}
});
});
//page nav
$("#page-nav li a").click(function(e) {
e.preventDefault();
$("#page-nav li a").removeClass('active');
$(this).addClass('active');
goToByScroll($(this).attr("href").replace("#", ""));
});
function goToByScroll(id){
$('html,body').animate({
scrollTop: $("#"+id).offset().top},
'slow');
}
And here is a working example over at codepen
How can I improve my javascript so that is performs a little smoother. As you can see when you click a link it still thinks it is within that section and the active class flickers.
Upvotes: 1
Views: 2318
Reputation: 18292
Your problem was that you were setting the active
class when you click an link and also when you move. What I did was to remove the class handling from the click
event handler and let the scroll
handler take care of everything. This way, there is no flicker. Here you have an updated CodePen.
$("#page-nav li a").click(function(e) {
e.preventDefault();
goToByScroll($(this).attr("href").replace("#", ""));
});
If this solution is not good enough for you, tell me and I'll think something more sophisticated.
New working solution here.
Basically, I created a variable that indicates whether you have clicked a link or not. If you have, then the scroll
handler won't change CSS classes (avoiding the flicker). Then, in the complete
handler of your animate
function, I set it to false again (allowing for class changes as you scroll):
var s = $("#page-nav"),
pos = s.position(),
linkClicked = false;
$(window).scroll(function() {
var windowpos = $(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("stick");
$('.main').css('margin-top', '60px');
} else {
s.removeClass("stick");
$('.main').removeAttr('style');
}
});
$(window).scroll(function() {
var y = $(this).scrollTop();
$('.linky').each(function (event) {
id = $(this).attr('href');
if (y >= $(id).offset().top) {
if (!linkClicked) {
$('.linky').not(this).removeClass('active');
$(this).addClass('active');
}
}
});
});
//page nav
$("#page-nav li a").click(function(e) {
e.preventDefault();
$("#page-nav li a").removeClass('active');
$(this).addClass('active');
linkClicked = true;
goToByScroll($(this).attr("href").replace("#", ""));
});
function goToByScroll(id){
$('html,body').animate({
scrollTop: $("#"+id).offset().top},
'slow', function() {
linkClicked = false;
});
}
Upvotes: 1