Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advanced jQuery sticky sidebar

I'm working on a (sticky) scrolling sidebar. The problem is that most sticky sidebars don't take into consideration that the sidebar can be taller then the viewport (e.g. if many items are added to the basket(sidebar)). Which is what I'm trying to solve. These are the requirements:

  • If the height of the sidebar is taller then the viewport, it should scroll through the content and the bottom of the div should stick to the bottom of the viewport when scrolling further down.

  • If the height of the sidebar is taller then the viewport, the divs underneath should only be shown when you are at the bottom of the page.

  • When user scrolls back up, the sidebar scrolls back to the top and sticks back onto the top of the viewport.

  • If the height of the sidebar is less then the viewport, it should be sticky from the top on when scrolling down.

So all in all quite some functionality and not that simple (I think). The closest I've seen to what I'm trying to achieve is this example: http://demo.techbrij.com/730/fix-sidebar-scrolling-jquery.php but the way the code is written doesn't fit into mine.

So far, this is what I've made: DEMO

And the jQuery code I used:

jQuery(document).ready(function($) {

var $sidebar   = $('.sidebar'),
    $content   = $('.content');

if ($sidebar.length > 0 && $content.length > 0) {
    var $window    = $(window),
        offset     = $sidebar.offset(),
        timer;

    $window.scroll(function() {
        clearTimeout(timer);
        timer = setTimeout(function() {
            if ($content.height() > $sidebar.height()) {
                var new_margin = $window.scrollTop() - offset.top;
                if ($window.scrollTop() > offset.top && ($sidebar.height()+new_margin) <= $content.height()) {
                    // Following the scroll...
                    $sidebar.stop().animate({ marginTop: new_margin });
                } else if (($sidebar.height()+new_margin) > $content.height()) {
                    // Reached the bottom...
                    $sidebar.stop().animate({ marginTop: $content.height()-$sidebar.height() });
                } else if ($window.scrollTop() <= offset.top) {
                    // Initial position...
                    $sidebar.stop().animate({ marginTop: 0 });
                }
            }
        }, 100); 
    });
}

});
like image 309
Yunowork Avatar asked Mar 25 '13 21:03

Yunowork


2 Answers

You are using margins to move the sticky sidebar around - I've found this to be a tricky way to handle your current ask (and potentially a heavier way).

In general, I like to simply add a class to the sidebar that makes it be "position: fixed" so the browser does the heavy lifting on keeping it locked.

For your current ask, you simply have to scroll that position fixed div (which is also made 100% height) programmatically based on how far down they have scrolled. Take a look at my example and see if this is the effect you are after: http://jsfiddle.net/ZHP52/1/

here's the jquery:

jQuery(document).ready(function($) {

var $sidebar   = $('.sidebar'),
    $content   = $('.content');

//Since our CSS is going to monkey with the height as you scroll, I need to know the initial height.
var sidebarHeight = $sidebar.height();

if ($sidebar.length > 0 && $content.length > 0) {
    var $window    = $(window),
        offset     = $sidebar.offset(),
        timer;

    $window.scroll(function() {

        if ($content.height() > sidebarHeight) {
            var new_margin = $window.scrollTop() - offset.top;
            if ($window.scrollTop() > offset.top) {
                // Fix sidebar
                $sidebar.addClass("fixed");
                // Scroll it the appropriate ammount
                $sidebar.scrollTop(new_margin);            
            }else{
                $sidebar.removeClass("fixed");
            }
        }
    });
}

});
like image 174
gcoladarci Avatar answered Oct 27 '22 02:10

gcoladarci


Check out hcSticky, I was just looking for this. It's kind of the "perfect" sticky sidebar and can also emulate the other libraries with options.

The first demo is probably what everyone needs, it scrolls a container independently from the main content. (you can go through the whole sidebar before reaching the bottom of the page or when you scroll bar up, before reaching the top of the page).

Check it out: http://someweblog.com/demo/hcsticky/

like image 21
Julien Iafrancesco Avatar answered Oct 27 '22 04:10

Julien Iafrancesco