user3550879
user3550879

Reputation: 3469

Solving the safari 'bounce' issue

I have code which animates my navigation up (off screen) when the user scrolls down, and animates it back down when the user scrolls up.

However, in Safari when the user scrolls up at faster speed, the page 'bounces' a bit at the top, which makes my navigation animate up when the user is at the top. Is there a way to solve this?

my code

jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight(true);

$(window).scroll(function(event) { didScroll = true; });

setInterval(function() {
if (didScroll) {
  hasScrolled();
  didScroll = false;
}
}, 100);

function hasScrolled() {
if($( window ).width() > 768) {
   var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
   return;
if (st > lastScrollTop) {
    // Scroll Down
        $('#screen-nav').removeClass('nav-down').addClass('nav-up');
   } else { 
        $('#screen-nav').removeClass('nav-up').addClass('nav-down');
   }  

 }
 lastScrollTop = st;
 }

});

Upvotes: 1

Views: 564

Answers (1)

BoffinBrain
BoffinBrain

Reputation: 6535

I'm actually quite surprised that Safari communicates negative overscrolling to the scripts, since it's a nonstandard technique. However, I think you just need to adjust your scroll condition to account for it:

if (st > lastScrollTop && lastScrollTop >= 0 && st > 0) {

These two additional checks will ensure that the menu doesn't get pushed up if the current scroll position or the previous scroll position were negative.

Since I didn't have Safari to test on, I simulated it by taking a page and pushing its body down by 100px, then performing the test by checking against the number 100 instead of 0:

jQuery("body")[0].id = "screen-nav";
jQuery("body").css("margin-top", "100px");

jQuery(document).ready(function($){
    var didScroll;
    var lastScrollTop = 0;
    var delta = 5;
    var navbarHeight = $('nav').outerHeight(true);

    $(window).scroll(function(event) {
        didScroll = true;
    });

    setInterval(function() {
        if (didScroll) {
        hasScrolled();
        didScroll = false;
        }
    }, 100);

    function hasScrolled() {
        if ($(window).width() > 768) {
            var st = $(this).scrollTop();
            if (Math.abs(lastScrollTop - st) <= delta) {
                return;
            }
            if (st > lastScrollTop && lastScrollTop >= 100 && st > 100) {
                $('#screen-nav').removeClass('nav-down').addClass('nav-up');
            } else {
                $('#screen-nav').removeClass('nav-up').addClass('nav-down');
            }
        }
        lastScrollTop = st;
    }
});

I'm a little confused about your use of both the onscroll event and a 100ms timer. You could implement your solution using one or the other, but there's no need to use both in combination. I'd probably use onscroll because there is less overhead when the user is not scrolling. Just something to consider.

Upvotes: 1

Related Questions