views:

313

answers:

4

I have a div which, when my page is first loaded, is about 100px from the top (it holds some buttons etc. for the page).

When a user scrolls past it, I would like the div to "follow" the user in that it attaches to the top of the screen. When the user returns to the top of the page, I want it back in its original position.

Visualization - xxxxx is the div:

Default (page load)          User vertically scrolled well past it
---------                    ---------
|       |                    |xxxxxxx| < after div reaches top of screen when
|xxxxxxx|                    |       |   page is scrolled vertically, it stays
|       |                    |       |   there
---------                    ---------
+1  A: 

Use position:fixed; and set the top:0;left:0;right:0;height:100px; and you should be able to have it "stick" to the top of the page.

<div style="position:fixed;top:0;left:0;right:0;height:100px;">Some buttons</div>
webdestroya
+1 fixed is the right thing to do - no JS, no horrible content jarringly chasing you down the page
annakata
It isn't always on top though, see my question and visualization. It is usually in the middle of the page (after loading the page fresh). I only want it to stay on top if the user scrolls vertically past it.
Alex
That doesn't seem to address the requirement that it not be at the very top of the screen when the user is scrolled all the way to the top.
bwarner
If you want it to stay after they scroll past it, it will likely require some javascript, and the "lag/catchup" that it shows is likely to cause some headaches for users.
webdestroya
If the JS that handles it is light weight enough, there won't be any noticeable "lag". I've seen plenty of sites doing this without a problem
Infinity
Disagree webdestroya, I don't see much "lag/catchup" in the example I gave in my answer, at least across IE7/8, FFox 3.6, Safari 4, and Chrome on a XP PC. http://perldoc.perl.org/perl.html
Andrew
A: 

There was a previous question today (no answers) that gave a good example of this functionality. You can check the relevant source code for specifics (search for "toolbar"), but basically they use a combination of webdestroya's solution and a bit of JavaScript:

  1. Page loads and element is position: static
  2. On scroll, the position is measured, and if the element is position: static and it's off the page then the element is flipped to position: fixed.

I'd recommend checking the aforementioned source code though, because they do handle some "gotchas" that you might not immediately think of, such as adjusting scroll position when clicking on anchor links.

Andrew
+4  A: 

The trick is that you have to set it as position:fixed, but only after the user has scrolled past it.

This is done with something like this, attaching a handler to the window.scroll event

   $(window).scroll(function() {
        var $stickyEl = $('#the-sticky-div'),
            windowTop = $(window).scrollTop(),
            elTop = $stickyEl.offset().top;

        if (windowTop > elTop)
            $stickyEl.addClass('sticky');
        else
            $stickyEl.removeClass('sticky');
    });

This simply adds a sticky CSS class when the page has scrolled past it, and removes the class when it's back up.

And the CSS class looks like this

  #the-sticky-div.sticky {
     position: fixed;
     top: 0;
  }
Infinity
I tried this, but I get horrible flickering every time I scroll :(
Alex
okay, I got it to work with saving the element top outside of the function. I think the re-evaluation on scroll caused the flicker (causing an update to top)
Alex
One more problem: When I turn the div into a FIXED div, the content below "jumps" upwards (by the height of the div), presumably because the div that was there before pushing it down is now gone/fixed. How do I fix that?
Alex
Yeah the element caching fix makes sense, although it seems to work smoothly on the page I borrowed this snippet from.. About the "jumping" issue..I don't know. Usually this kind of trick is used for sidebars and things like that, stuff whose layout doesn't affect other elements position in the page.For example like this: http://viixii.com (scroll down). If you can't accomodate, maybe you can do something in the scroll handler that appends a `<div style="height:{height of the sticky div}"></div>` whenever the sticky div gets `sticky`. This would compensate for the layout reflow. Makes sense?
Infinity
Were you using a complicated jquery selector to get the element? That could be causing the flickering. Anyhow caching it in a var is a good idea.
Infinity
Or alternatively instead of appending a div you could just adjust the `margin-top` of the element that's jumping around to match the FIXED div's height.. e.g. `$stickyEl.next().css('margin-top', $stickyEl.height())`
Infinity
A: 

Does any one know how to make sticky div on Safari ipad version

Scott Chu at Taiwan