2

I use the following javascript to make a 'sticky' navigation, which makes the nav fixed to the top of the screen when the user has scrolled past it. This code works fine, although when the element is made sticky and the position of the element is set to 'fixed', the position of all of the following elements in the body 'jump up' to occupy the gap created from changing the element from relative to fixed, and makes a slight 'jolting' effect. To counter this, I have tried adding an offset to the scroll y position when the element is changed to fixed, but this causes a loop by triggering the scroll function again, and the page scrolls to the bottom of the page.

So my question is - how in the function below can I add an offset to the scroll position? ie, how can I set the scroll position in the $(window).scroll function, without triggering the $(window).scroll function into a loop?

 $(window).scroll(function (event) {

    var y = $(this).scrollTop();

    var top = $('#main-navigation').offset().top;

    if (y >= top) {
        $('#navigation').addClass('fixed');
    }
    else {
        $('#navigation').removeClass('fixed');
    }
});

Any help is very much appreciated

1
  • 2
    you can add event.preventDefault() to stop the execution of the default scroll behavior of window. also, could you make a Fiddle where we can see the issue? Commented Sep 20, 2014 at 13:39

2 Answers 2

3

General solution

Here is a general solution to prevent the loop:

var lastScrollTop = 0;
var defaultScrollHandler = function(e)
{
    var y = $(this).scrollTop();

    //change event handlers    
    $(window).off("scroll", defaultScrollHandler);
    $(window).on("scroll", tmpScrollHandler);

    var jumpHeight = 200;

    if(lastScrollTop > y)
        jumpHeight *= -1;

    var newY = y + jumpHeight;

    $(window).scrollTop(y + jumpHeight);
};

var tmpScrollHandler = function()
{
    lastScrollTop = $(this).scrollTop();

    //change event handlers back
    $(window).off("scroll", tmpScrollHandler);
    $(window).on("scroll", defaultScrollHandler);
};

$(window).on("scroll", defaultScrollHandler);

http://jsfiddle.net/udcwgyub/

Before you set the new scroll position you can disable the current event handler and register another handler for the scroll event. After you set the new scroll position the other handler will be called. This handler will disable itself and register the actual handler again.

Better solution for your case

I think in your case you could better replace the static navigation by a dummy element which should have the same height as the navigation.

var navOffset = $("nav").offset().top;

$("#dummyNav").height($("nav").innerHeight());

$(window).scroll(function(){

    var y = $(this).scrollTop();

    var $nav = $("nav");
    var $dummyNav = $("#dummyNav");

    if(y >= navOffset)
    {
        if(!$nav.hasClass("fixed"))
        {
            $nav.addClass("fixed");
            $dummyNav.show();
        }
    }
    else if($nav.hasClass("fixed"))
    {
        $nav.removeClass("fixed");
        $dummyNav.hide();
    }

});

http://jsfiddle.net/wdup394c/

Sign up to request clarification or add additional context in comments.

Comments

1

The easiest solution is to temporary replace scroll event subscription.

// initial subscribe to scroll event
this.$el.on("scroll", this.handleScroll);

// unsubscribe initial handler and subscribe fake handler before manual scroll
this.$el.off("scroll");
this.$el.on("scroll", () =>
{
    this.$el.off("scroll");
    this.$el.on("scroll", this.handleScroll);
});

// scroll manually
this.$el.scrollTop(0);

However, if scroll event doesn't happen during manual scroll (during this.$el.scrollTop(0);), then handler will not be called on first scroll event. In this case, during first event, fake event will be unsubscribed, and original one re-subscribed, but will not called.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.