Tutorial: jQuery “Sticky Sidebar”

by Andrew on February 19, 2012

Description

More and more, I’m seeing sites that have certain “sticky content” (elements that remain in view as the user scrolls the page). In most cases, keeping elements in view can be achieved by simply setting the CSS positioning of that element to “fixed.”

This approach solves many basic situations, but sometimes you’ll want to have the content set to fixed only after the user has reached a specific scrolling threshold on the page. In the following example, I will explain how to achieve this.

Make sure this is what you’re looking for – View Demo | Download

Note: This code requires jQuery.

Step 1

First, find the top of the “sticky” object (in relation to the window) and store it in a variable. As you can see, I’ve chosen to use the class “sticky” for the object I want to remain in view.

$(function(){ // document ready

  var stickyTop = $('.sticky').offset().top; // returns number   

});

If you’re not familiar with jQuery’s Document Ready, you can read about it by following the link.

Step 2

Create an anonymous function that is called when the window scroll event fires. At the same time, you’ll want to store the current position of the window top in a variable. The value of this variable will be changed every time the user scrolls the window.

$(function(){ // document ready 

  var stickyTop = $('.sticky').offset().top; // returns number    

  $(window).scroll(function(){ // scroll event

    var windowTop = $(window).scrollTop(); // returns number

  });

});

Step 3

Create an if statement that asks whether the top of the window is greater than the top of the sticky element. If true, the element will be set to fixed positioning. Otherwise, it will be set to static positioning.

$(function(){ // document ready

  var stickyTop = $('.sticky').offset().top; // returns number 

  $(window).scroll(function(){ // scroll event	

    var windowTop = $(window).scrollTop(); // returns number

    if (stickyTop < windowTop) {
      $('.sticky').css({ position: 'fixed', top: 0 });
    }
    else {
      $('.sticky').css('position','static');
    }

  });

});

That's it. You're done!

Note: The CSS property "top" is set to 0 when the element is fixed positioned. If you find the element jumps when you reach the scroll threshold, play around with this value. Sometimes the margins of the content within the sticky element can affect where the element sits in relation to the top of the window.

Step 4 (Optional)

You might consider including an additional wrapping if statement which only calls the scroll event function when an element with the class "sticky" is present in the DOM.

If the element is universally throughout the site (i.e. your site header), this won't be an issue. However if the element is only on certain pages, you will get an error when loading pages where the sticky element does not exist. To safeguard against this, add the following code:

$(function(){ // document ready

  if (!!$('.sticky').offset()) { // make sure ".sticky" element exists

    var stickyTop = $('.sticky').offset().top; // returns number 

    $(window).scroll(function(){ // scroll event

      var windowTop = $(window).scrollTop(); // returns number 

      if (stickyTop < windowTop){
        $('.sticky').css({ position: 'fixed', top: 0 });
      }
      else {
        $('.sticky').css('position','static');
      }

    });

  }

});

Conclusion

This is really just the beginning of what you can do with scrolling thresholds. You can put whatever code you like within the anonymous function we created and have it run once the threshold is met. Try it out!

Demo

View Demo | Download

Feedback

Did this tutorial help you? Could this tutorial be improved? Let me know in the comments!

Thanks to Mitgux, ___mohsen, and _joshnh for their feedback.

  • http://about.me/cleiva Carlos Leiva Burotto

    Hi andrew! 

    I’m trying to apply the same ‘sticky effect’ with the last box that appears in the sidebar of andesbeat.com (it currently display a 160×600 banner).

     I’m working with jQuery 1.7.1
    and the jQuery function is being loaded at the end of the page

    The element  i’m talking about says: 

    I followed the same steps you mentioned but I can’t make it to work as expected! :/

    What is wrong?? would you mind to check my website ? thanks in advance!

    • http://thebeersessions.com Andrew Henderson

      Hi Carlos,

      Cool site! You have a JavaScript error for the reference to NivoSlider that’s breaking any JavaScript calls afterward.”Uncaught TypeError: Object [object Object] has no method ‘nivoSlider”

      Are you using NivoSlider elsewhere on the site? You should remove it from this page since it doesn’t seem to be implemented.  Try that and let me know if that solves it.

      • http://about.me/cleiva Carlos Leiva Burotto

        @AHendy:disqus it worked like a charm!!!! thanks so much!! can’t explain how grateful i’m ! 

        I posted a question in Forrst two days ago:http://forrst.com/posts/Is_this_effect_a_float_box_or_a_sticky_box-daj Joshua Hibert gave me some feedback, but I couldn’t make it to work as expected, you and Joshua rock!

        One last question (i’m newbie with jQuery and Javascript as you can see):

        How can someone add a limit to the movement of the sticky box??
        Now the sticky box works as I wanted, but it overlays the footer, and I would like that the sticky box could move until 20px of reaching the footer

        * Actually, the same thing happens with the social-box that appears in the left side when you’re reading an article.. it overlays the footer, and i also want to allow it’s movement 20px before the footer

        Thanks for your words about the site. It started almost 90 days ago, and as you see, now we’re only two people working, and I’m in charge of tweaking the site, generating content, research, etc..

        Thanks a lot for your feedback!!!!

        • http://thebeersessions.com Andrew Henderson

          Threw this together quickly, but it should work. See demo http://andrewhenderson.me/wp-content/tutorials/jquery-sticky-content/index2.html


          $(function(){ // document ready

          if (!!$('.sticky').length) { // make sure ".sticky" element exists

          var el = $('.sticky');
          var stickyTop = $('.sticky').offset().top; // returns number
          var footerTop = $('#footer').offset().top; // returns number
          var stickyHeight = $('.sticky').height();
          var limit = footerTop - stickyHeight - 20;

          $(window).scroll(function(){ // scroll event

          var windowTop = $(window).scrollTop(); // returns number

          if (stickyTop < windowTop){
          el.css({ position: 'fixed', top: 0 });
          }
          else {
          el.css('position','static');
          }

          if (limit < windowTop) {
          var diff = limit - windowTop;
          el.css({top: diff});
          }

          });

          }

          });

          • http://about.me/cleiva Carlos Leiva Burotto

            it worked!!!!! 

          • http://twitter.com/madmaxpower16 Michael Gleeson

            Thanks a million this worked a charm

  • guest

    I dont get it implementent on my website… i use wordpress, and follow your steps.

    i add the function code in the header before the tag and add to my sidebar:

    div id=”widget” class=”sticky”>Sticky WidgetLorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam interdum luctus eros sed pretium. Proin turpis odio, viverra et tincidunt nec, tincidunt sed nisl.

    but it dont realy work :(

  • Hans Spiess

    thanks for the snippet! 

    using this addition, it would also work on resize.  $(window).resize(function(){    if ($(‘.sticky’).offset()) {      var parentwidth = $(‘.sticky’).parent().width();      var offset = $(‘.sticky’).parent().offset();      $(‘.sticky’).css({ width: parentwidth – 40, left: offset.left });    }  });

  • http://www.geekandblogger.com/ Pavan Somu

    Awesome plugin. Hope we can increase search ranking and AD revenue with sticky sidebar!

  • http://www.wiyono05.blogspot.com/ Wiyono

    Really nice….

  • Trashfunkel

    Thank you !!!

  • Jeff

    I need this to work with a fluid layout. I tried Hans Spiess’s snippet, but it didnt seem to work properly. Anybody have a thought?

    • http://thebeersessions.com Andrew Henderson

      It should work on a fluid layout. I actually never understood the need for Hans’ addition. It works for me on window resize. Maybe I’m not understanding something here. Can you provide an demo of where the code fails. Thanks!

      • Hans

        i must admit i wasn’t clear at this point. my markup was sort of:

        <div class="push right"> <nav class="sticky pagenav"> nav list.. </nav></div><div class="pull left"> content…</div>

        so the nav bar is positioned right to the content, but when position: static is applied, it breaks the layout.

        normally i’d put the content first, but it is only a ‘on-page-navigation’ with anchors, so i thought it behaves as a page index and should reside on top of the content.

        sorry for the confusion :)

  • elkaz

    Thanks for the script. Thought it might be worth mentioning that if there is multiple sticky elements on a page then the first one to trigger the if statement will change every .sticky element to static positioning. While this is ideal if there are multiple sticky classes in the same sidebar but I would suggest perhaps a $.each loop that will only set the current element to static if it meets the requirements and for the use case of having multiple sticky elements in a single sidebar instead wrap these elements in a single sticky class.

    • http://thebeersessions.com Andrew Henderson

      My pleasure elkaz.

      Yes, if you have multiple elements with the class “sticky,” they will all be set to position fixed once the first element reaches the “windowTop”.

      I wouldn’t recommend using multiple sticky classes in the same sidebar. I would do as you suggest and wrap everything that I want to move with the visitor in the sticky class since that entire DOM element is now the “sticky content”.

      Taking into consideration that there might be multiple sticky elements spread throughout the DOM would be a nice feature. For instance, if you had a three column layout, you could then have the visitor pick up sticky content on either sidebar without interfering with one another’s positioning.

      I’ll write this up at some point.

      Thanks!

  • http://twitter.com/tayanc Hasan Tayanç

    Hi Andrew. Any idea defining scroll limit to ajax loaded sticky div? Sticky div height is changeable and the scroll event can not update the sticky div height dynamically.

  • ana ramirez

    Hi Andrew. Any Idea How can I sticky the element in the middle of the screen? Thanks a lot. Ana

    • http://thebeersessions.com Andrew Henderson

      Hi Ana. To keep it simple, you could add a key value of left positioning:

      if (stickyTop < windowTop){ $('.sticky').css({ position: 'fixed', top: 0, left:YOUR-VALUE-HERE });}

      • ana

        Hi Andrew,

        Thanks for the quick reply.
        But what I need is that the Sidebar not exceeding half of the screen.
        I try with:
        if (stickyTop < windowTop){ $('.sticky').css({ position: 'fixed', top: ( "50%" )}); }

        But the "sidebar" still is moving to the top of the page and then returns to the middle of the screen.
        Any Idea of how to stop moving her when arrives to the half of the screen.
        Thanks a lot.

      • ana

        Hi Andrew,

        Thanks for the quick reply.
        But what I need is that the Sidebar not exceeding half of the screen.
        I try with:
        if (stickyTop < windowTop){ $('.sticky').css({ position: 'fixed', top: ( "50%" )}); }

        But the "sidebar" still is moving to the top of the page and then returns to the middle of the screen.
        Any Idea of how to stop moving her when arrives to the half of the screen.
        Thanks a lot.

  • Ravi Gupta

    Thanks, its matches my requirements

  • Rox

    Hi Andrew, wonder how you’d do it with several sticky divs?

    Rox

    • http://thebeersessions.com Andrew Henderson

      Hi Rox,

      Several people have asked about this, so I’m developing a plugin that accounts for this scenario. I should have it posted tonight or tomorrow. I’ll be looking forward to feedback!

    • http://thebeersessions.com Andrew Henderson

      Hi Rox, I’ve created a plugin that allows for this:
      https://github.com/AndrewHenderson/jSticky

  • http://thebeersessions.com Andrew Henderson

    If anyone is interested, I’ve created a plugin for this which handles multiple sticky elements. It’s still being refined and I also need to add some documentation, but I’ll be looking forward to feedback.

    https://github.com/AndrewHenderson/jSticky

    To use, simply call $(“#foo”).sticky();

    You can also set options for top spacing, z-indexing (if you want to stack sticky elements), and defining a stop point or element on the page.

    $(“#foo”).sticky({
    topSpacing: 60,
    zIndex: 3,
    stopper: ‘#bar’
    });

    • geniusbleu

      Hi Andrew, thanks for your awesome script. I tried this new version with the stopper. It works very well, but unfortunately I have a problem with the stop point. The sticky div stops below the point where it should stop. I believe this is because of the css. Could you please post the basic css code? I mean just the css code that’s needed to make the script work, without any unnecessary code? I don’t know why it stops below the stopping div, any help would be really appreciated. Thanks

      My Css is:

      #can_soc {
      float:left;
      width: 80px;
      }
      #can_text {
      float:left;
      width: 620px;
      }
      .can_soc_box {
      width:80px;
      }

      My Html is:

      Sticky banner

      [Blog Article]

       

      stopstickyban is the stopping div. The problem is that the Sticky Banner goes and stops below the #stopstickybandiv. Thank you

  • Sachin

    Hi,
    How i can make it Ipad compatible? It’s seems not working on Ipad.

    • http://thebeersessions.com Andrew Henderson

      Hi Sachin. From what I’ve read, I don’t believe there is a solution for having fixed position elements on an iPad. I personally don’t have an iPad, so it makes it harder to develop. Again, my understanding is that the consensus is to have a responsive design that doesn’t use a fixed position element on mobile devices.

  • Krax

    Hi Andrew,
    Thanks for this wonderful work. I have a problem why implementing this on my site. The sticky bar is overlapping on the content. Am using it with twitter bootstrap. The question is how do I prevent the sidebar from overlapping when in sticky mode? Please see the attached image for clarification.

    • http://thebeersessions.com Andrew Henderson

      Hi Krax, it looks like you need to define a width for the sidebar in your stylesheet.

    • http://thebeersessions.com Andrew Henderson

      Hi Krax. It looks like you need to define a width for the sidebar in your stylesheet.

      I created a plugin for this: https://github.com/andrewhenderson/jsticky

      Twitter Bootstrap 2.1.0 released the affix plugin which might help you out as well. http://twitter.github.com/bootstrap/javascript.html#affix

      • Krax

        wow! That was very prompt…I really appreciate this. It is working fine now; after defining the width in my stylesheet. I have spent hours figuring it out. Thanks so much.

  • Krax

    Hi Andrew,

    Another question. Because am using responsive design, and because I now have a fixed width for the sidebar, it does not adjust very well again to different screen resolutions! Do you have any suggestion how I can target different screen resolution with that sidebar implementation?

    • http://thebeersessions.com Andrew Henderson

      You could use media queries to set the width of the sidebar specific the device’s screen width. For instance:

      @media (min-width: 480px) and (max-width: 979px) {

      .sidebar { width: DESIRED WIDTH }

      }

      At smaller screen sizes, a common technique is to switch off fixed positioning. It doesn’t work well anyway on touch devices. Instead put it at the top of the page stacked at fluid width. Take a look at how Twitter Bootstrap does it in their documentation pages by resizing your browser.
      Hope that helps!

  • Ondrej

    Hi, nice,
    I just didnt get it, how it works with position fixed, when this is measure from viewport and not from parent element? (When I set top:0 I have my sticky on the left corner of viewport)

    thanks

    Ondrej

    • http://thebeersessions.com Andrew Henderson

      Hi Ondrej. Can you provide a link to a reduced test case?

    • dgruetter

      Of all the stuff I did that went wrong. This went so right.. the first time! Thanks for this easy to follow tutorial.

      • http://andrewhenderson.me/ Andrew Henderson

        Haha! Thanks for the positive feedback. I’m hoping to post a new one soon.

  • rmunozz

    Dear Henderson…
    Your plugin rocks. I just have a question as a newbe on the jQuery world. How is it possible to set the possition of the sticky to stop at certain point of the stage?.. I mean, I want to have a sticky div but that don’t overlap the footer.

    Could you give me a glimps please?

    Warming regards!

    • rmunozz

      I did something like this to achive what I want..

      if (!!$(‘.sticky’).offset()) { //

      var stickyTop = $(‘.sticky’).offset().top; // regresa la posicion del freno de arriba
      var footerStop =$(‘#footer’).offset().top;

      $(window).scroll(function(){ // scroll event

      var windowTop = $(window).scrollTop(); // returns number

      if (stickyTop > windowTop || windowTop == footerStop){
      $(‘.sticky’).css(‘position’,'static’);

      }
      else {
      $(‘.sticky’).css({ position: ‘fixed’, top: 0 });

      }

      });

      }

    • http://thebeersessions.com Andrew Henderson

      Thanks rmunnoz! Glad you’re finding it useful. Take a look at the comment below. It links to a jQuery plugin I wrote and host on GitHub. It solves this issue by passing the id of the stopper. See here: http://andrewhenderson.me/tutorial/jquery-sticky-sidebar/#comment-648162155

      • rmunozz

        Dear Andrew

        I highly, highly apreciate your help. One more question, hope you can helpme and save my life. I’m tring to make sticky a elastic div (this div resize its content while the user resize the window). Is the blue div http://www.sixplus1.com/inventmx/funcionalidad_tres/sixplus_e.html

        But I can’t understand the logic to adjust the div using the plugin you setup. I mean If I resize the window the sticky goes over the rest of the content. I’m tring to adjust the z-index of the div, but I’m not lucky. Could you give me some advices to adapt it.

        THANKYOU VERY MUCH!!

  • Pingback: JQuery: Sticky Float Share Button, Menus, Widget, Sidebar etc. - Shellcreeper.com

  • Justin

    Terribly sorry if this is a stupid question, but is there any way to cancel this out if the unser is on a mobile device? (tablet/phone)….Thank you!

    • Hans
      • http://andrewhenderson.me/ Andrew Henderson

        As far as I know, there is no particular test for mobile. I suspect you’re looking to avoid sticky elements on touch devices. I recommend testing for touch using Modernizr (http://modernizr.com). Then you can only apply method when the device is non-touch screen.

        Hope this helps!

        • Harel

          var w = $(window).width();

          if(w > 1024) {
          sticky code
          }

          • http://andrewhenderson.me/ Andrew Henderson

            This is only a test for the size of the browser window. If you added this, it would keep the sticky sidebar from running in instances where his desktop browser was narrower than 1024px.

          • Ryan

            I think Harel is saying that since mobile screen sizes are quite small, it is safe to assume that users using that screen size is probably on mobile. Additionally, if formatted correctly, shouldn’t detract from the experience if the user is on a laptop or tablet and opted for a smaller screen size.

  • DVS

    i don’t understan nothitg

  • erwin

    thanks

  • http://twitter.com/aguidis Adrien Guidis

    Thx a lot for your clear explanations :)

  • bumbar

    This script is very useful, and I already use it.
    But I have one question.
    When scrolling further down, some page elements close sticky div

    Perhaps this is z-index issue.

    Some page elements are shown above sticky div…

    Thank you!

  • Sang

    Hello Andrew, I’m a little new to this and a little confused. The floating sidebar is something I’ve been looking to implement on my site. My site runs on wordpress and I have no idea where to insert the code in my theme. I’m not sure if you are familiar with it or not but would this snippet of code go in the functions.php or the index.php file?

    Thank you in advance.

    • http://andrewhenderson.me/ Andrew Henderson

      This is JavaScript code, so it would go in a .js file. If you know you only need to target the sidebar, look at the HTML and hook into the sidebar’s id or class. Replace ‘.sticky’ in the code snippets from the article with that.

      Based on how you phrased your question, I’m going to also mention that this code uses jQuery. If you’re not comfortable writing JavaScript and jQuery, it might be hard to implement this.

  • Pingback: Project: Sticky Sidebar | Skillcrush

  • Carlos

    Hi Andrew. I would like to switch positions between the sidebar and the article divs, placing the sidebar to the left and the article to the right. When doing so, the footer div gets below the sidebar, not at the bottom, and overlaps the sidebar. This should be quite simple, but I’m stuck!

    Thanks for your help.

    • http://andrewhenderson.me/ Andrew Henderson

      When an element takes a fixed positioning, it no longer occupies real estate in the document, so the footer then positions itself below whatever static elements precede it.
      A way to solve this, is to wrap the element that is “sticky” in a transparent static div of equal height and width. When the scroll threshold is met, the sticky element moves, leaving behind its container to hold it’s place.
      The plugin I have on GitHub solves this with a different approach, by using jQuery’s clone method. This is more costly in that it actually redraws all of the elements content within that container, but it works well and it should solve your issue.
      Hope that helps!

      • http://andrewhenderson.me/ Andrew Henderson

        Just as a follow up, I removed the clone feature from the GitHub plugin. I’m using an empty div instead which is more performant. https://github.com/AndrewHenderson/jSticky

  • Krid

    If the panel increses in height, lets say its a shopping basket and the user adds many items to it, thus expanding the height of the sticky DIV, what happens when the height of the DIV exceeds the bottom of the screen?

    • http://andrewhenderson.me/ Andrew Henderson

      You want to add a stopper. This is a feature of the jQuery plugin I wrote after this post.
      https://github.com/AndrewHenderson/jSticky. Give it a try and let me know if it solves your issue.

      Note: If the div itself is taller than the height of the viewport and at that point the non-sticky content doesn’t force a vertical scrollbar, you’ll want to add a line or two that sets the max height of the sticky div to whatever the viewport height is.

  • Akash

    Ohk, this is something really awesome! I used it in my project and it just worked in 5 mins. Great!

  • http://www.facebook.com/ulrike.schoneich Ulrike Nilsson Schoneich

    This works great in IE, Firefox and Opera, however in Chrome and Safari my sticky sidebar jumps to the top of the screen as soon as you start scrolling. I’m also using the responsive bootstrap and the sidebar is contained in a “row-fluid span2″…any ideas how to fix this?

    • http://andrewhenderson.me/ Andrew Henderson

      Hard to say without seeing the page. Can you provide a link? Are you using the plugin I wrote or did you write it yourself using the tutorial?

  • Surjith SM

    if websites having long sidebar, this may not work. i found this as my choice. http://web3canvas.com/item/jquery-sticky-for-long-sidebar/

    • http://andrewhenderson.me/ Andrew Henderson

      That’s an interesting approach. The plugin I wrote works with tall sidebars by providing a stopper or stopping point. It’s more robust than this tutorial. The only difference is the link you provided starts the sticky effect halfway down the sidebar displaying the full sidebar before the sticky effect begins.
      Thanks for sharing! Always nice to see other solutions.

  • Andrew Morris

    Hey Andrew,

    This is fantastic, but I have one problem with it, the event doesn’t fire if your body element is set to height:100% (I do this to have a sidebar that can scroll independently of the main content with overflow:auto).

    How would you set the variable as say a div like ‘main-content’ so when it reaches the top of that div it locks to the stop of the screen?

    • http://andrewhenderson.me/ Andrew Henderson

      Might try using offset top again:

      $(‘.main-content’).offset().top;

      Instead of:

      $(window).scrollTop();

  • http://www.facebook.com/mateo.jovani Mateo Jovani

    Thank u so much!

  • Lois

    Trying to use your JSticky and my sticky div is floating to right but when I start to scroll it jumps to the left. Any ideas?
    Thanks in advance! :)

    • http://andrewhenderson.me/ Andrew Henderson

      I take it you’re using the plugin. Can you provide a link to you page?

      • Lois

        The site is uploaded to my college’s server at the following:
        http://mikespestcontrol.webtech.iowacentral.com/

        • Lois

          Thanks for the quick response, I didn’t expect you to answer me so quickly. I sent you my initial message before I had to get to work so I didn’t see your response til the next day.
          Were you able to access my site ok? I’ve updated it and its still acting goofy.

          • Lois

            K, I almost gave up but I finally got it to work. Looks like I had to have an inner div with the sticky class. I had my navigation in a “sidebar2″ div with the sticky class on it but I needed to create a inner div to put the sticky class on, and the outer div is like just a case I guess (and shouldn’t have had the sticky class on it). Still can’t figure out why it doesn’t stay in the confines of the container div and behave the same. Oh well lol.

            Anyhoo, thanks for the great code! :)

          • http://andrewhenderson.me/ Andrew Henderson

            I took a quick peek yesterday. Glad you were able to work through it!

  • javiertroya

    Excelente tutorial para crear capas pegadisas!

  • http://www.facebook.com/dragos.rizescu.7 Dragos Rizescu

    How would you approach this for a responsive layout where the sidebar follows only if the width is larger than 768?

  • mateusz

    It is not working when the windows is resized and width is not big enough to show sidebar.

    • http://andrewhenderson.me/ Andrew Henderson

      Have you tried using the plugin? I link to it in the sidebar.

      • mateusz

        there is a problem in image.

  • Bert

    My sticky box contains an image that is dynamic in height so the height is not set. In Chrome v26 when hard refresh it intermittently overlaps the footer as if it does not include the image in the sticky box’s height. Any ideas?

    • http://andrewhenderson.me/ Andrew Henderson

      Try calling the sticky method after the image height is set.

  • Pago

    Hey thanks for your tutorial.
    I’ve got a problem with safari. it just doesnt work in that browser. In the rest its fine. The only time it pops to its right place (the window top), its when I scroll over my galerie. Any guess?

  • Cory Dobson

    Great tutorial, I will definitely be trying this out. One additional feature I’m going to need on my site is the ability to set the element back to static positioning once it reaches the footer, so it doesn’t keep fixed position over the footer as they scroll further down. Do you know how that can be done?

    • http://andrewhenderson.me/ Andrew Henderson

      Thanks, Corey. Try the plugin I wrote. See if that works for you. It stops the sticky element at whatever stopping point you set. It can be either a px value or another element on the page (i.e. the footer).

  • Jen

    Great tutorial! So I am using JQuery UI, and there’s 2 divs above the div I want sticky; the first is expanded by default, and the other is collapsed by default. If I collapse the first div, or expand the second div, it throws off the calculation for the sticky header because it’s position has changed. I’m still a newbie with jQuery… what would be the best way to accomplish this?

    Thank you!

    • http://andrewhenderson.me/ Andrew Henderson

      Thanks, Jen. Move the variable of stickyTop inside of the scroll event function:

      $(window).scroll(function(){

      var stickyTop = $(‘.sticky’).offset().top;
      var windowTop = $(window).scrollTop();

      });

      • Jen

        Thanks! So that does work regarding the resizing, but once the sticky header reaches the top of the page and I keep scrolling, the sticky header flickers as I scroll. Any ideas? I tried zIndex to no avail.

        • http://andrewhenderson.me/ Andrew Henderson

          Move that var stickyTop back outside of the scroll event function and wrap it in a function called setStickyTop. This will allow you to call that function when you click those collapsible panels, thus reestablishing the stickyTop position for the window scroll event to compare.

          function setStickyTop() {
          var stickyTop = $(‘.sticky’).offset().top;
          };

          setStickyTop();

          $(window).scroll(function(){ // scroll event
          var windowTop = $(window).scrollTop(); // returns number

          });

          // Later On…

          $(‘.collapsible’).on(‘click’, function() {
          setStickyTop();
          });

          • Jen

            Hmm not sure if I am doing this right. My div isn’t sticking anymore (haven’t tried the click function yet, wanted to make sure this worked first).. this is the code I am using. Does that look right?

            $(function(){

            function setStickyTop() {
            var stickyTop = $(‘#gview_activeProjects .ui-jqgrid-hbox’).offset().top;
            };

            setStickyTop();

            $(window).scroll(function(){

            var windowTop = $(window).scrollTop();

            if (stickyTop < windowTop) {
            $('#gview_activeProjects .ui-jqgrid-hbox').css({ position: 'fixed', top: 0, zIndex: 9999 });
            }
            else {
            $('#gview_activeProjects .ui-jqgrid-hbox').css('position','static');
            }

            });

            });

          • http://andrewhenderson.me/ Andrew Henderson

            That’s my fault. The code I gave you was incorrect. Need to brush up on my Disqus inline coding.

            The var is within the scope of that function. Change it to this:

            var stickyTop = $(‘#gview_activeProjects .ui-jqgrid-hbox’).offset().top;

            function setStickyTop() {
            stickyTop = $(‘#gview_activeProjects .ui-jqgrid-hbox’).offset().top;
            };

            The setter function now simply sets the value of the variable that is now available within the scope of your document ready function, rather than defining it with “var”.

            The point of this named function “setStickyTop” is so that you can call it when you click the collapsible elements. This event handler will also need to be within the scope of this same document ready function.

          • Jen

            Works like a charm! THANK YOU SO MUCH!!! :) You have no idea how long I’ve been looking for plugins to handle this! :) But it’s always nice to be hands on and actually learn what the code is doing.

          • Jen

            Sorry to bug you, but I have one more question… is there a way to add a stopper into this code, or would I have to use the plugin?

            Thank you!

          • http://andrewhenderson.me/ Andrew Henderson

            The plugin is pretty much this code with a stopper. I would suggest using that instead. It’s not that much code, so you could always take a look if you feel confident, try to port the stopper functionality.

          • Jen

            Sounds good, thanks!

  • Andrew

    Hi , I like this method and I would like to add a delay time to the sticky content but I don’t know how to do that. Do you? Thanks for your kind help!

    This is my code… eventually I need the content to move down a bit that’s way the 0 + …

    $(function(){ // document ready
    if (!!$(‘.sticky’).offset()) { // make sure “.sticky” element exists
    var stickyTop = $(‘.sticky’).offset().top; // returns number
    $(window).scroll(function(){ // scroll event
    var windowTop = $(window).scrollTop(); // returns number
    var newstickyTop = 0 + windowTop – stickyTop;
    if (stickyTop < windowTop){
    $('.sticky').css({top: newstickyTop });
    }
    else {
    $('.sticky').css({top: 0});
    }
    });
    }

  • Steven

    Great plugin you wrote! helped a lot of people.
    Somehow i try it in IE 6 but it seem like does not work at all. Any Idea?

    • http://andrewhenderson.me/ Andrew Henderson

      Sorry, I haven’t tested in IE6. If you have to support IE6, I feel for you.

  • Rick

    Hi, great and clear documentation. It works with text and image content in the box that gets fixed. but when a Flash animation is in the DIV, the Flash disappears when the DIV gets fixed, and it reappears when you scroll up (revert to static). Any clue why this is the case?

  • coding

    This is an awesome article, really clear, useful and concise. I had been battling with ‘affix’ on bootstrap to no avail, but I found this article and it worked perfectly, thanks!

  • Hosein

    Thank you! This was so simple and easy.

  • luciana

    Hi … i have tried your tips and trick … but it don’t work,
    please help … any suggest?
    my site http://hair4tomorrow.com
    i want to sticky the Media.net Ads 300×600 in the sidebar

  • Nikhilesh

    If the sticky DIV is having more than one page content than how can we make it scroll with browser’s main scroll bar till its content finishes. And once it’s content finishes it remains stick while the main body contents scroll ?

    • http://andrewhenderson.me/ Andrew Henderson

      Set an explicit height on the sticky container and make sure it has an overflow: auto. When scrolling inside the sticky element the browser should handle the rest.

  • http://www.1like4.me/ 1like4me

    hi Sir,
    I tried this and it works fine! Just wanna know if it is possible to use it with multiple divs.. I want my header and a part of my sidebar to stick when scroll.
    I only know about css and not about js..

    Thanks for this code :)

    • http://andrewhenderson.me/ Andrew Henderson

      Glad it worked for you. I wrote plugin that handles multiple sticky elements. I link to the Github repo in the sidebar.

  • Ahmet Talut Taşgıran

    Thank you. This awesome.

  • RexMonday

    This is brilliant and works very well… except that my sticky div is within a div that has its width set as a percentage (and a max-width). When I scroll down, the width of the sticky div immediately increases to the max-width.
    Am I missing something really obvious?

    • http://audiosex.pro/ SAiNT

      i’m facing the same problem. I’m not very good with JavaScript, but i suppose we need request the current width of the element the same way we did with $(‘.sticky’).offset().top;

      Andrew, please help me out here

      • http://andrewhenderson.me/ Andrew Henderson

        Try the plugin on GitHub. Let me know if that doesn’t work.

      • http://audiosex.pro/ SAiNT

        did it…
        and that is all it takes!!!!! huge problem solved with just .width()
        was it so hard to listen to me and do this when i first suggested it?… :-

        like they say, “wanna do something right, do it yourself”…

        • http://dusk.is/ Rhys Jones

          Brilliant and simple, exactly what I was looking for.

  • Barbara

    Thanks that is exactly what I needed!!!

  • Pleth

    Fantastic explanation. This is one of the clearest tutorials I’ve seen around the interwebs. Thank you!

  • http://www.kwameosei.com/ Kwame Osei

    Thanks this is great!

  • http://myskins.org/ Envira

    Thanks for great tutorial , i used it for Navigation rather than sidebar :P
    Worked like a charm after some tweaks :)

  • Kaushik

    Andrew, i have found out another way which works without doctype declaration, http://www.hklabs.org/articles/create_floating_sidebar
    but as soon as i put the doctype declaration, it dosent work!!

    • http://andrewhenderson.me/ Andrew Henderson

      Probably something in the code that is invalid in doctypes other than HTML5. I glanced at the tutorial quickly. Start by adding type=”text/javascript” to your script blocks. Earlier doctypes requires this attribute. I have a feeling that will fix it. If not, look at what other HTML5 valid omissions might not work in HTML 4.

      If a stop point is what you’re after, it might be easier to use my plugin – https://github.com/AndrewHenderson/jSticky

  • Mordor

    This is great, basically only code that works how it should (all the other solutions I’ve found on the web are having awlays at least one major problem). Thanks!

    Could I just ask, when I am using exactly code from the post, how I achieve that the .sticky will stop some distance before reaching bottom of the page? (so it becames static again before reaching bottom). I tried to modify your code like this:

    $(function(){ // document ready

    var stickyTop = $(‘.sticky’).offset().top; // returns number
    var scrollPosition = window.pageYOffset;
    $(window).scroll(function(){ // scroll event

    var windowTop = $(window).scrollTop(); // returns number
    var windowBottom = $(document).height();; // heigh of the document
    var stopscroll = windowBottom – 1500; // 1500px before bottom

    if (stickyTop = scrollPosition ) {
    $(‘.sticky’).css(‘position’,'static’);
    }

    else {
    $(‘.sticky’).css(‘position’,'static’);
    }

    });
    });

    But it doesn’t seem to be working (it just doesn’t stops that 1500px before the bottom of the page). Can you help pls? Thank you!

    • http://andrewhenderson.me/ Andrew Henderson

      Thank you. Glad it’s helpful.

      I wanted that feature as well, so I included it in my plugin. Take a look. It should be easy to use: https://github.com/AndrewHenderson/jSticky

  • http://mimoYmima.com/ Brent Lagerman

    You rule Andrew. You got it in like 15 lines where some of the other scripts have close to 100 and they don’t work as good. Thanks for sharing this!

  • bonmenu

    the best solution for this i ever seen! thanks! )

  • Adi

    hello. i have a big issue. please change the distance to top from 0 to 50

    $(‘.sticky’).css({ position: ‘fixed’, top: 50 });

    now, see what’s happening. how can we prevent that crazy jumping? the box should slide smooth till it reaches 50px from the top and than stay thare, not jump like crazy down. i try to avoid that so any ideea how to fix it? thanks

    • http://www.terramar.co/ 344kellogg

      I’d like to know how to resolve this also.

      • http://andrewhenderson.me/ Andrew Henderson

        Change stickyTop < windowTop to stickyTop – 50 < windowTop

        This will make the threshold 50px sooner than the elements actual position.

        • http://www.terramar.co/ 344kellogg

          That worked perfectly! Thanks.

  • Bardo

    Thanks, this was a clean simple solution to keep my sidebar navigation sticky without a ton of code or html overhead.

  • acd

    fuck u, beech

  • zabarov

    I loved it. Works just perfectly. Thank you so much.

  • Greg London

    Worked, thanks, now I just need to figure out how to stop it at footer..

    • http://andrewhenderson.me/ Andrew Henderson

      Check out the plugin on GitHub. It has a stop point option.

      • Greg London

        I checked that out, didn’t help, I’m trying to grab the scroll end of page to hack it and make it do what I want.. Close now…

  • http://www.callum-macdonald.com/ Callum Macdonald

    Awesome article, thanks, still relevant. My only suggestion would be to use the `.css({})` format in both `.css()` calls, only because I think it makes the code a little more consistent and therefore easier to understand.

  • kris

    Wow, Your code are readable and awesome. I like the way you show the code on site. No problem while I read your code.

  • achmadtk07

    Thanks you really helped me make the work of the client company’s website ..

  • davidzupec

    Hello, would this work with a sidebar in WordPress? Unfortuantely I can’t get it to work. Thank you!

    • http://andrewhenderson.me/ Andrew Henderson

      The approach should work with any DOM element.

      • davidzupec

        Thanks Andrew I got it to work!

  • Tomas

    Many thanks, exactly what I needed…without any extra scripts and works fine on mobile devices :)

  • Jaya Sankar

    Hi Andrew,

    I am totally new to Jquery and all that stuff , I am designing an application of our own office internal application . I want a div position fixed , but when coming to the end of the page it should be placed at a position and again when scrollling top t should become fixed again, hope that you understood my problem . so please help me on this.

    Thanks,
    Jay.

  • katrina

    immensely helpful. thank you!

  • HanSoloShotFirst

    Andrew, fantastic plugin. One request. I would like to add a class to the element once it becomes fixed, much like bootstrap does with affix-top, affix-bottom, etc. Any plans to add to plugin? Or know if a way to do it? It would be great if there was a variable for adding class. An example is that the width changes when becoming fixed and I would like to only add a set width once it becomes fixed.

    $(‘#sb’).sticky({

    topSpacing: 61, // Space between element and top of the viewport
    //zIndex: 100, // z-index
    class: ‘affix-top’, // something like this feature would be great //
    stopper: “#footer” // Id, class, or number value

    });

  • http://nativeimaging.com/ Native Imaging

    Hi Andrew. Thank you for this script. However, i’m reluctant to use this in my WordPress theme since it generates a duplicate placeholder of the html generated by my widgets. It generates duplicate content for everything therein including my widget elements. I guess this is a method for the stopper to push the sticky div up once it hits the footer or an area you don’t want to overflow? Is there a way to just do that without having a placeholder generated? Also, i’m using masonry.js for my footer widget placement, and the stopper function doesn’t actually work with my theme.

    Thank You for this script, I will try my best to make use of it before I try another one.

  • Luiz

    Hello, do u know how can i make like a fab sidebar? see fab.com Thanks.

    • http://andrewhenderson.me/ Andrew Henderson

      You mean the header on that site?

Next post: