I\'m attempting to make the navigation bar stick to the top, when the user scrolls down to the nav bar and then unstick when the user scrolls back up past the navbar. I unde
You can do that with some easy jQuery:
http://jsfiddle.net/jpXjH/6/
var elementPosition = $('#navigation').offset();
$(window).scroll(function(){
if($(window).scrollTop() > elementPosition.top){
$('#navigation').css('position','fixed').css('top','0');
} else {
$('#navigation').css('position','static');
}
});
There are some problems implementing this which the original accepted answer does not answer:
onscroll
event of the window is firing very often. This
implies that you either have to use a very performant listener, or
you have to delay the listener somehow. jQuery Creator John Resig
states here how a
delayed mechanism can be implemented, and the reasons why you should
do it. In my opinion, given todays browsers and environments, a
performant listener will do as well. Here is an implementation of the pattern suggested by John Resigposition: fixed
, the page will "jump" a little because the document "looses" the height of the element. You can get rid of that by adding the height to the scrollTop
and replace the lost height in the document body with another object. You can also use that object to determine if the sticky item has already been moved to position: fixed
and reduce the calls to the code reverting position: fixed
to the original state: Look at the fiddle herescrollTop
on every call. Since the interval bound handler has also its drawbacks, I'll go as far as to argue here that you can reattach the event listener to the original scroll Event to make it feel snappier without many worries. You'll have to profile it though, on every browser you target / support. See it working hereHere's the code:
JS
/* Initialize sticky outside the event listener as a cached selector.
* Also, initialize any needed variables outside the listener for
* performance reasons - no variable instantiation is happening inside the listener.
*/
var sticky = $('#sticky'),
stickyClone,
stickyTop = sticky.offset().top,
scrollTop,
scrolled = false,
$window = $(window);
/* Bind the scroll Event */
$window.on('scroll', function (e) {
scrollTop = $window.scrollTop();
if (scrollTop >= stickyTop && !stickyClone) {
/* Attach a clone to replace the "missing" body height */
stickyClone = sticky.clone().prop('id', sticky.prop('id') + '-clone')
stickyClone = stickyClone.insertBefore(sticky);
sticky.addClass('fixed');
} else if (scrollTop < stickyTop && stickyClone) {
/* Since sticky is in the viewport again, we can remove the clone and the class */
stickyClone.remove();
stickyClone = null;
sticky.removeClass('fixed');
}
});
CSS
body {
margin: 0
}
.sticky {
padding: 1em;
background: black;
color: white;
width: 100%
}
.sticky.fixed {
position: fixed;
top: 0;
left: 0;
}
.content {
padding: 1em
}
HTML
<div class="container">
<div id="page-above" class="content">
<h2>Some Content above sticky</h2>
...some long text...
</div>
<div id="sticky" class="sticky">This is sticky</div>
<div id="page-content" class="content">
<h2>Some Random Page Content</h2>...some really long text...
</div>
</div>
I wouldn't bother with jQuery or LESS. A javascript framework is overkill in my opinion.
window.addEventListener('scroll', function (evt) {
// This value is your scroll distance from the top
var distance_from_top = document.body.scrollTop;
// The user has scrolled to the tippy top of the page. Set appropriate style.
if (distance_from_top === 0) {
}
// The user has scrolled down the page.
if(distance_from_top > 0) {
}
});
Most easiest way to do it as follow:
var elementPosition = $('#navigation').offset();
$(window).scroll(function(){
if($(window).scrollTop() > elementPosition.top){
$('#navigation').css('position','fixed').css('top','0');
} else {
$('#navigation').css('position','static');
}
});