I have a simple script that basically waits till my navigation has scrolled off the screen, resizes it slightly then it animates in from the top of the screen and remains fixed till i scroll back up.
When you scroll past the menu it animates back in, but then repeats this animation every time I finish scrolling. I have tried adding the animation outside of the scroll function but then it doesn't animate at all.
Have i missed something simple?
var Header = $('#header'),
Navbar = $('.navbar'),
links = $(".navbar ul.nav > li > a"),
HeaderH = Header.height(),
NavbarH = Navbar.height();
$(window).scroll(function () {
if ($(this).scrollTop() > (HeaderH + NavbarH)) {
Navbar.addClass('navbar-fixed-top')
links.css('padding', '10px 20px 10px 20px');
Header.css('margin-bottom', '64px');
Navbar.css('top', '-64px').animate({'top' : '0'}, 1000);
}
else{
Navbar.removeClass('navbar-fixed-top')
links.css('padding', '20px');
}
});
The site is built on joomla with bootstrap, hence the navbar-fixed-top style classes.
Your scroll handler will be called multiple times as the user scrolls.
To illustrate this, if you add a console log
$(window).on('scroll', function(){
console.log('scroll');
});
You'll see "scroll" output multiple times as you scroll down. This is because each little gradation of scroll fires off a scroll event.
A common approach is to wrap your callback in a debounce function, so it only runs once in a given period, even if more scroll events are fired.
Tweak your code like so:
function scrollHandler() {
if ($(this).scrollTop() > (HeaderH + NavbarH)) { Navbar.addClass('navbar-fixed-top') links.css('padding', '10px 20px 10px 20px'); Header.css('margin-bottom', '64px'); Navbar.css('top', '-64px').animate({'top': '0'}, 1000); } else { Navbar.removeClass('navbar-fixed-top') links.css('padding', '20px'); } } $(window).scroll($.debounce(750, scrollHandler));
This will make it respond only for one scroll event per 750 milliseconds - change the duration to your taste.
Stackoverflow code block is freaking out for some reason - please note the "function scrollHandler(){" line above.
A more economical approach
A more concise way of doing the same thing is to check if the scroll event's been fired in a given period and if it hasn't to assume the user's stopped scrolling. This solution is borrowed from this other question .
function scrollHandler() {
if ($(this).scrollTop() > (HeaderH + NavbarH)) {
Navbar.addClass('navbar-fixed-top');
links.css('padding', '10px 20px 10px 20px');
Header.css('margin-bottom', '64px');
Navbar.css('top', '-64px').animate({'top': '0'}, 1000);
}
else {
Navbar.removeClass('navbar-fixed-top');
links.css('padding', '20px');
}
}
$(window).on('scroll', function () {
clearTimeout($.data(this, 'timer'));
$.data(this, 'timer', setTimeout(function () {
scrollHandler();
}, 250));
});
This method doesn't give you the same options and potential for re-use you get with the debounce plugin - the plugin lets you choose whether to call your callback at the start or the end of your period - but it's slimmer.
Try something like
var Header = $('#header'),
Navbar = $('.navbar'),
links = $(".navbar ul.nav > li > a"),
HeaderH = Header.height(),
NavbarH = Navbar.height();
var scrolled = false;
$(window).scroll(function () {
if ($(this).scrollTop() > (HeaderH + NavbarH) && !scrolled) {
Navbar.addClass('navbar-fixed-top')
links.css('padding', '10px 20px 10px 20px');
Header.css('margin-bottom', '64px');
Navbar.css('top', '-64px').animate({'top' : '0'}, 1000);
scrolled = true;
}
else{
Navbar.removeClass('navbar-fixed-top')
links.css('padding', '20px');
scrolled = false;
}
});
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.