user2738640
user2738640

Reputation: 1227

jQuery sticky header flashes at specific height

I am using following code to make a menu sticky when the window is scrolled down. It works fine if the window height is enough to scroll down the full header area, but it it creates problem is the height is just close enough to scroll, in that case it starts flashing and does not let scroll.

Here is the demo of the problem, refresh couple of times and try to scroll down. I have set the body height to 622px to reproduce the problem:

http://jsbin.com/ipEROYO/1

Here's the code I'm trying:

$(document).ready(function() {
    var stickyNavTop = $('.nav').offset().top;

    var stickyNav = function(){
        var scrollTop = $(window).scrollTop(); 
        if (scrollTop > stickyNavTop) { 
            $('.nav').addClass('sticky');
        } else {
            $('.nav').removeClass('sticky'); 
        }
    };

    stickyNav();

    $(window).scroll(function() {
        stickyNav();
    });
});

CSS:

.sticky {
    position: fixed;
    width: 100%;
    left: 0;
    top: 0;
    z-index: 100;
    border-top: 0;
}

Upvotes: 3

Views: 3937

Answers (4)

Alex W
Alex W

Reputation: 38253

It's because when you are setting the navigation div to position:fixed you are shortening the length of the document (by the height of that div), which then causes the scroll bar to go away, which causes the scrollTop() value to be 0 which causes the .nav div to be position:static and it is an endless cycle if you keep scrolling down.

Here's my quick solution:

$(document).ready(function() {
    var height = $('.nav').outerHeight();
    $(window).scroll(function() {
            if($(this).scrollTop() > height)
            {
                $('.nav').css('position','fixed');
                $('body').css('padding-bottom',height+'px');
            }
            else if($(this).scrollTop() <= height)
            {
                $('.nav').css('position','static');
                $('body').css('padding-bottom','0');
            }
    });
    $(window).scroll();
});

Upvotes: 4

Keith V
Keith V

Reputation: 730

Just modified the JSbin. Check it out. You were really close, just doing more than you needed to like setting the sticky class on load of the page rather than when the function first runs. Let me know if this helps.

Upvotes: 1

cage rattler
cage rattler

Reputation: 1597

Strongly recommend a CSS only solution for this layout. No one seems to know what to call this method, so I've been referring to it as the absolute stretch technique, but in my experience it works beautifully across mobile devices and PC's including all major browsers except IE6 and below. There is some discussion of it here.

body, .header, .nav, .mainContent{
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}

body, .mainContent {
    bottom: 0;
}

.header{
    height: 120px;
}

.nav{
    height: 70px;
    top: 120px;
}

.mainContent{
    top: 190px;
    overflow: auto;
}

You'll find you can get very robust, concise, well organized layouts in this manner, and fixed headers, footers and sidebars follow very easily.

Upvotes: 0

user1970409
user1970409

Reputation: 53

try that

     $(window).scroll(function () {

            var scroll_top = $(this).scrollTop();
               if (scroll_top > 66) {//height of header
                 $('.nav').addClass('sticky');
              } else {
              $('.nav').removeClass('sticky');
              }
       });

Upvotes: 0

Related Questions