I am working on a sticky nav for a website currently, and I am running into a few problems, when the nav bees position:fixed
it seems to jump and it looks "clunky", here is a fiddle of what I am trying to do,
/
Ideally the oute would be the user scrolls and the nav is not in a fixed position until it is scrolled out of the viewport it then bees fixed and and slides back into view.
I am working on a sticky nav for a website currently, and I am running into a few problems, when the nav bees position:fixed
it seems to jump and it looks "clunky", here is a fiddle of what I am trying to do,
http://jsfiddle/DKtLR/
Ideally the oute would be the user scrolls and the nav is not in a fixed position until it is scrolled out of the viewport it then bees fixed and and slides back into view.
Share Improve this question asked Jul 18, 2012 at 9:36 UddersUdders 7,00627 gold badges108 silver badges207 bronze badges 4- 2 how will this work in this example? the menu is already at the top of the page, there isn't any case where the user's viewport is above the menu. this will probably work better if the menu is not at the top of the page. – Rodik Commented Jul 18, 2012 at 9:40
- I would also say: if it's already on top of the page leave it there and fix it right away. If it's not, scroll it until it hits the ceiling and than fix it. – insertusernamehere Commented Jul 18, 2012 at 9:47
- Thats what I am trying to do, but it feels like there is a jump when it bees fixed – Udders Commented Jul 18, 2012 at 9:48
- 1 You should take a look at this one. – morgi Commented Jul 18, 2012 at 9:48
4 Answers
Reset to default 2Since you only want it to bee fixed when it is pletely out of viewport, then slide in, just modify the top
property and then animate it back into view. See this fiddle for a working example.
UPDATE
This updated fiddle should work better, as it only applies the behaviour if not already applied, and pletely removes dynamic styles when returning to normal 'static' position.
Note there is still a flicker when scrolling back up - this is because the nav 'jumps' from its fixed position back to its static position. This can easily be resolved using a similar technique to the animation above.
You can simply use the StickyScroller jquery plugin: http://vertstudios./blog/jquery-sticky-scroller-position-fixed-plugin/
At top and then fixed with animation so it's not clunky
This might be the solution you're looking for because it provides the fixed menu bar when scrolled out of the view, but when it switches from top to fixed, it does a slide-down animation, so it doesn't feel as you described it clunky.
HTML I've used in the example (simplified):
<div id="menu">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
...
</ul>
</div>
<div id="content" />
CSS is of course simple (only relevant styles)
#menu {
position: absolute;
width: 100%;
}
#menu.out {
position: fixed;
}
#menu ul {
margin: 0;
list-style: none;
}
#menu ul li {
display: inline-block;
}
And the script that does it and does so quickly (so it performs as fast as possible because the slowest part is the call to browser native getBoundingClientRect()
function which means it's still fast, very fast):
$(function() {
// save element references for faster execution
var menu = $("#menu");
var ul = menu.find("ul");
var content = $("#content")[0];
// get menu actual height
var menuHeight = menu[0].getBoundingClientRect().bottom;
// detect whether menu is scrolled out
var inView= true;
$(document).scroll(function(evt) {
evt.preventDefault();
var top = content.getBoundingClientRect().top;
var nextInView = (top + menuHeight) > 0;
// did state change so we have to change menu positioning
if (inView ^ nextInView)
{
inView = nextInView;
if (inView)
{
menu.removeClass("out");
}
else
{
menu.addClass("out");
ul.hide().slideDown("fast");
}
}
});
});
And this is it. You could also tweak the animation from slideDown()
to slide in
by animating top style property while you know exactly how many pixels above the view port you have to put the menu before the animation.
When you scroll the page and menu gets out of the view, it switches it to fixed position and scrolls the menu down so it dosesn't just jump in view but rather smoothly gets back in.
I made this alternative solution based on this solution. Based on the setInterval
function (see also console log).
var interval_id = false;
var curOffset, oldOffset;
var altmenu;
$(document).ready(function(){
altmenu = $('.top-nav')[0].cloneNode(true);
altmenu.style.position = 'absolute';
altmenu.style.display = 'none';
document.body.appendChild(altmenu);
oldOffset = $(window).scrollTop();
$(document).bind('scroll',function(){
if (interval_id) {
return;
}
//altmenu.style.display = 'none'; // optional
interval_id = setInterval(function() {
curOffset = $(window).scrollTop();
if(curOffset == oldOffset) {
console.log('scrolling stopped',curOffset);
clearInterval(interval_id);
interval_id = false;
if (curOffset>120) {
altmenu.style.display = 'block';
} else {
altmenu.style.display = 'none';
}
$(altmenu).css({
top: (curOffset-120)+'px'
}).animate({
top: (curOffset)+'px'
}, 500);
}
oldOffset = curOffset;
}, 500); //setInterval
});//scroll
});//ready
Test script and jsfiddle are here.