Sticky navbar makes content jump on way back up

2019-09-03 12:52发布

问题:

I Have a simple site set up with a header, navbar and content. When the page reaches the navbar, the position becomes fixed so the navbar sits at the top of the page - at this point, the navbar height also gets a bit smaller (as I like this effect) - I have done this by adding separate classes, fixed and thinner to the navbar.

Most people are aware of the issue that occurs when you add "position:fixed" to an inline element in that it makes the content suddenly "jump" upwards. To counteract this i have added a div called "stop_the_jump" which is hidden until the navbar becomes fixed, at which point it is displayed in it's place. All of this runs smoothly on the way down, but as you scroll back up you get a jump due to the fact that the navbar is now thinner.

I'm pulling my hair out over this one, how can I eliminate this jump that occurs on the way back up.

Here is a JSFiddle clearly showing my issue: http://jsfiddle.net/gnac14qa/

My jQuery code is as follows:

$(window).scroll(function() {    

var Scroll = $(window).scrollTop();
var ScrollFXfullHeight = $('.header-wrapper').height();

if (Scroll == ScrollFXfullHeight) {

$("#navigation").addClass("fixed");
$(".stop_the_jump").css('display','block');

} else if (Scroll > ScrollFXfullHeight) {
if(!$("#navigation").hasClass('fixed')) {
    $(".stop_the_jump").css('display','block');
    $("#navigation").addClass("fixed");
}
$("#navigation").addClass("thinner"); 
} else {
$("#navigation").removeClass("thinner fixed");
$(".stop_the_jump").removeClass("thinner");
$(".stop_the_jump").css('display','none');
}
});

Any help would be much appreciated.

回答1:

The jumping is created because you are changing the heights of the nav bar when its fixed and when its not fixed (60px vs 80px). This causes a mismatch in the space between the bottom of the nav bar and the top of the static content. You can make this transition look a bit better with the following code (but if you would consider not changing the height of the navbar, or perhaps create smaller increments in which you increase/decrease the size of the nav bar depending on scroll location, that would make the transition from fixed to not fixed seamless) demo here: http://jsfiddle.net/gnac14qa/3/

if (Scroll-18 == ScrollFXfullHeight) { // 18 looks better, the offset is actual 20px but 20 looks choppy

    $("#navigation").addClass("fixed");
    $(".stop_the_jump").css('display','block');

} else if (Scroll-22 > ScrollFXfullHeight) { // 22 looks better for the same reason above
    if(!$("#navigation").hasClass('fixed')) {
        $(".stop_the_jump").css('display','block');
        $("#navigation").addClass("fixed");
    }
    $("#navigation").addClass("thinner"); 
}

Also, you have two css class references that are the same (you can just combine them

.stop_the_jump {
    width:100%;
    float:none;
    display:none;
    background:green;
}
.stop_the_jump {
    height:80px; // can be moved to the class above
}

Heres what I mean by not switching the height of the navbar: http://jsfiddle.net/gnac14qa/4/

#navigation.thinner {
    width:100%;
    height:80px !important;  //kept at 80px instead of changing to 60px
}


回答2:

Ok so I came up with a solution based on the answers above. Essentially the issue is caused by the fact that a) the navbar resizes aswell as becomes fixed and b) The navbar resizes with a transition - so it's not an immediate change in size

The way I got around this is to stage the change in the position attribute and the size change. First the position changes to fixed at the same time as the "stop_the_jump" div is displayed, then once the page clears the height of "stop_the_jump" (which is the same size as the menu) then the "thinner" class is added making the menu thinner.

This now works seamlessly. Thanks to the above answers for pointing me in the right direction - here is my final code:

$(window).scroll(function() {    

var Scroll = $(window).scrollTop();
var ScrollFXfullHeight = $('.header-wrapper').height();

if (Scroll == ScrollFXfullHeight) {
$("#navigation").addClass("fixed");
$(".stop_the_jump").css('display','block');

} else if (Scroll > ScrollFXfullHeight) {
if(!$("#navigation").hasClass('fixed')) {
    $(".stop_the_jump").css('display','block');
    $("#navigation").addClass("fixed");
}
if (Scroll > ScrollFXfullHeight+80) {
$("#navigation").addClass("thinner"); 
}
else {
$("#navigation").removeClass("thinner");
}
} else {
$("#navigation").removeClass("thinner fixed");
$(".stop_the_jump").removeClass("thinner");
$(".stop_the_jump").css('display','none');
}

});

and a link to the updated JSfiddle: http://jsfiddle.net/gnac14qa/6/