We've been working on a couple of projects lately in which we wanted their statically positioned sidebars to stick to the top of the page when you scroll down. When the first project came along, I said "... I can do this" right before writing some custom javascript with hard-coded values. When the second project came along, my instinctual hatred for writing the same code over and over again kicked in and I wrote StickyScroll—a surprisingly (to me at least) flexible and compact jQuery plugin to take care of the heavy lifting.

Update: This post was written some time ago, and not all of its information is up-to-date. Please go to StickyScroll's GitHub page for the latest instructions or to report bugs

The main idea here is that these sticky elements need to be contained in some way. Obviously, when scrolling up a page, the sticky element needs to stop sticking when it returns to its original position. But I would argue that almost equally important is having a bottom boundary on the page where the sticky element will stop sticking so that it doesn't spill into the footer or even outside of the page itself. With no options provided, the plugin will use the <body> element as the bottom boundary. If you want to customize the bottom boundary, there's two approaches you can take:

1. Specify the containing parent

You probably want the div.sticky element to be contained within the div#container.

How to make it so:

$('.sticky').stickyScroll({ container: '#container' });

2. Specifying a bottom boundary

One of the snags I came across was having an element that I wanted to be sticky, but it didn't have any special parent element to be contained within. In this case, there is a "manual" mode where you can specify a pixel offset, relative to the bottom of the document, as the bottom boundary for your sticky elements.

Example:

$('.sticky').stickyScroll({ mode: "manual", bottomBoundary: 150 });

In this example, the bottom of the sticky element will never be closer than 150 pixels away from the bottom of the document.

Use it

If you have use for it, try it out and let me know what you think.

A few notes:

Requires jQuery 1.4+Though, if you're like us, and you have constraints that don't let you upgrade to 1.4 quite yet, you can rip some code out from the jQuery source and make it work. Everything you need is here.

Using the container method does not mean that position: relative will be set on the container. StickyScroll does not alter the styling of anything other than the element it is called on.

We employ position: fixed styling on the sticky element, so IE6 is not supported

49 Comments

KB ~
7 years ago

I would love to see a working demo of this. I'm so far unable to get the script to work within an existing page, so I'm not sure if I'm not declaring the element that should be stuck correctly or am missing CSS (there's no info on the "sticky-process" selector called in the script?). I've been trying to modify existing scripts to do just what this one does, so I would be thrilled to get this working.

Wesley ~
7 years ago

Nice plugin, KB, the reason it's not working is because there is a syntax error in the script. Line 82 should be changed to simply "};" without ().

A few kinks for me though:

My div is 1 of 2 columns (each 49.1% wide). Due to the plugin the div's width increases on first scroll.

Secondly, when I scroll back up it goes beyond it's original position. I would want it contained to where it was if possible.

And thirdly, an "easing" animation option instead of this fixed design would be great.

@Wesley - I like that the solution you found doesn't require fixed positioning, especially since fixed positioning doesn't quite work how you would expect on the iPhone/iPad. I'm not sold on animations, as I imagine there would be a delay between scrolling and the sticky element moving to the position you just scrolled.

KB ~
7 years ago

Thanks, Rick! Works like a charm.

I was trying to modify another script that used the animation approach for the reason you stated: there had to be a delay between the scrolling and animating as otherwise the div would jerk up and down while scrolling. I'll most likely build a separate mobile/iPhone/iPad version for this project, but the issue with fixed positioning is good to know.

Nintensity ~
7 years ago

Hey! Thanks for the plugin. But unfortunately, I have uncovered a bug!

It works when the web layout is designed with a fixed grid. On a fluid grid layout, it would work, however, the location where the fixed container will stop upon scrolldown will vary because the content's height will expand/contract depending on the user's window size.

You're right -- I didn't consider fluid layouts. I'll try to add support for them.

Nintensity ~
7 years ago

Thanks Rick!!! I really appreciate your work in helping me and for others. Once you get it going on a fluid grid... This plugin is gonna be the bomb!

Mark ~
7 years ago

Rick...
First off, thanks for the code!! I was incorporating it today and noticed this. Hopefully you can follow me around this explanation. I have a page that starts short with no scroll bars and then grows longer if a user selects a checkbox that grows the page to a length with scroll bars. Browser is Safari so the scroll bars are hidden until the page needs them. Before the page grows the sticky div works as expected. After the page grows and the scroll bars are added and you scroll down the div does move with the top of the browser but it also jumps to the right approximately the distance of the added scroll bars. I assumed this had to do with the leftOffset. I've moved the leftOffset to inside the onScroll() function so that it is constantly getting calculated. I did this with no knowledge of the consequences but now it works like it should. Here is the code. It'd be great to know if this is a bad thing or a good thing. http://pastie.org/1158890

I can see where the plugin, as it is now, wouldn't react well to dynamically changing layouts, especially horizontal ones. Your code looks logical, I'll test it out and if it still looks good I'll add it in.

In the meantime, if you don't like having that extra calculation every time the scroll event gets called, you can add html { overflow-y: scroll; } to your global CSS file to force a scrollbar, even when you don't need it. IE7 does this by default, and believe it or not, I've come to prefer it. It makes going through pages that may or may not require scrolling more consistent.

Mark ~
7 years ago

How in the world have I never thought of that to force the scroll bar. It is basically my only gripe when developing sites and viewing them in Safari, my default browser. Thanks again!!

Nintensity ~
7 years ago

Hey Rick, I definitely appreciate the effort help to make this plugin.. but I assure you, once you get it working, it's gonna be the bomb!

No progress. I have looked at it and tested out some ideas, but I think support for fluid layouts is going to be left out for now.

I have two ideas for how I'm pretty sure I could make it work, but one requires extra markup and one would cause a momentary flash of style, potentially causing a flickering/disappearing sticky element whenever the window is resized, and I'm not satisfied enough with either of those compromises to add support in.

You are, though, more than welcome to fork it on Github and add what you need to it :)

Is there a way to use this so, for example, a div is placed on the bottom-right of a screen and fixed, and when you reach the footer of the page, the div then scrolls up and stays atop the footer? Also, if the footer is high on the page (as if the content weren't enough to take up the full page and make it scrollable), could that div still sit atop of the footer?

First things first: we're working with Javascript here, not Java. Similar names, but very different languages.

Secondly, no, StickyScroll doesn't do what you're describing. This plugin really only applies to elements that start out statically positioned on the page (that is to say, not fixed at all), and then become fixed (or "sticky") to the window as you scroll past them). The plugin doesn't really help if the element in question starts out fixed.

What you want to do and what StickyScroll does for you are pretty similar, though. It would be possible to adapt the plugin or extract some code to do what you need. Lines 69-120 in jquery.stickyscroll.js are the main chunk of it. It's pretty poorly commented, so I apologize in advance for that. I'll try to add some helpful comments soon.

To give you a visual, it's kinda like a puzzle. This element (approx. 150px x 150px), when you load the page, looks fixed to the content wrapper, like 50px from the bottom and 50px from the left of the wrapper's border. As you scroll it stays put, until you reach the footer (approx. 300px). Once it hits the footer, it moves with the rest of the document to the bottom. When you scroll back up, it returns to it's set position on the screen.

I hope that gives you a better idea of what I am thinking.

I've been searching for upwards of 15 total hours and I can't find anything that's just right. All tutorials I've seen are basically written to keep things toward the top of a page, I just don't know how to convert them to work on the bottom.

Yeah, that's pretty much what I was imagining. The problem is that StickyScroll is meant to do a pretty specific thing well, and not try to solve every single problem. So, it's really good at making a specific kind of sticky sidebar, which doesn't include one that sticks to the bottom of the page, like what you're describing.

Like I said, the logic from StickyScroll could be extracted and edited to do what you need, but I can't promise that functionality will be incorporated into the plugin. Sorry to disappoint!

evan ~
7 years ago

Its a great plugin to have however, there doesn't seem to be a way of positioning the element you want to be sticky. For example, i'm using this sticky plugin to allow the nav bar (that sits at the top of my page), to scroll with the user until a certain point on my page, which I have working fine. When the page is initially loaded the positioning of my nav is how I want it to look (40px from the top) but as soon as I start to scroll down the page it jumps to the very top of the browser window & remains there. How do I ensure my nav stays 40px from the top always? I can't seem to style this sticky element when it is active?

How do you position the element initially? Since StickyScroll takes care of any relative/absolute/fixed positioning for you, be sure that your element starts out statically positioned and use margin or padding (margin is probably the more correct answer, but padding is probably safer with StickyScroll) to position it, and everything should be great.

Evan ~
7 years ago

Still no luck i'm afraid. Its position is fixed but even after changing it to static, it still reproduces the same problem. It also then interferes with the rest of my style sheet & the way i've coded up the page as the nav then disappears behind other elements. Here is what I have for the nav element (i.e. the element I would like to be sticky):

Look at the README on the Github page for the latest usage instructions, as this page is kind of out of date. It sounds like you're using the "manual" mode, for which the usage is a little bit different now than what this page says. You can play around with your margins/padding and the topBoundary setting until you get it right.

If your element is going behind your other page elements, use z-index. Even though the initial positioning is static, the z-index will take effect once StickyScroll has done its thing.

Hope this helps!

evan ~
7 years ago

Thanks for your help on this, i'm not that great at scripting & this probably really basic but how do I implement the following code (taken from the usage instructions on GitHub):

Well, there's two problems here, really. The first is that it's not meant to be used with anything less than jQuery 1.4. The second being the StickyScroll isn't really meant for use anymore. It's broken in the latest versions of Safari, Chrome, and Firefox, and for now I'm taking it as a sign that man was not supposed to imitate fixed positioning with Javascript. Both of those warnings are up on the Github page. Sorry to disappoint!

Michal ~
6 years ago

Im not behind my pc now. In the evening ill post what you need

Michal ~
6 years ago

It all works you just need tobtweak everything ill send everything later.

I have just started to use StickyScroll (initially overlooking the warning on GitHub). Anyway, I had problems in Internet Explorer. After a bit of debugging, I realized that my problem was the call to Date.now, which is not supported by IE until version 9. I couldn't really figure out why the time was needed, so I just tried to remove the call to Date.now(). So I use:

id = index,

instead of

id = Date.now() + index,

According to my tests, this works fine in IE8, Firefox 8.01, Chrome 15.0.874.121 and Safari 5.1.2.

If you can give me a hint about why the date/time is necessary, it would be much appreciated :-)

Sorry, this script is outdated and isn't seeing updates anymore. The flickering started happening some time ago and I never came up with a solution to fix it. There's more info on the github page about it.

If Internet Explorer is not that important, you could just add to the elementtransition: all 0.2s ease-in-out;

Then play around with .sticky-active and .sticky-inactive

Craig Moss ~
6 years ago

Thanks for the great plugin Rick, worked with a bit of tom foolery, had to adjust the topBoundary so it would not do a funny bounce when scrolling back to top, this sorted out the problem even if it always sets the margin from the top...see my script code below for more information

Great plugin Rick. It works fine for me except the sidebar doesn't stop within the bottom of the container. I have no idea why. My sidebar is an Ad Banner Tower of 160x600 and it doesnt stop within the bottom of the container. I have the container set to overflow:hidden so it is actually getting cut off. If I dont have overflow:hidden then the sidebar overflows on to the footer. I am using the auto mode and cannot use the manual flow as the container size is dynamically determined. Please help!!!

Bennart ~
5 years ago

nice plugin
but how i can animate the sticky div when scrolling?

Visitor ~
5 years ago

Um in your demo the stickied element jumps up and down instead of staying fixed in place... like fidgeting or something...

Visitor ~
5 years ago

How about a top boundary so it's always X pixels away from the top? Is there an option for that?

thủ thuật ~
4 years ago

Great script!
is there any chance to apply some easing, when the position changes?
As far I experienced it' quite jumpy / flickering while scrolling the page.