jQuery Sticky Scroller / Position:Fixed Plugin

The jQuery sticky scroll effect is a trending effect that has great user experience capabilities. One of the most cited examples of the sticky scroller effect is found at Blue Sky Resumes. While the effect at Blue Sky is pretty neat, we see that it doesn't leave many options. 90% of sticky scroller plugins only give the developer the ability to end the scrolling object at a certain point. I felt that there was a large opportunity gap that we need to fill.

STOP! Before you read any further

This plugin is intended to solve a very specific problem: Triggering callbacks at certain intervals of scrolling with a fixed object. If you would like to simply switch an item from position: fixed to position:absolute/static based on how far you've scrolled, or any other simple scroll callbacks, you need to check out jQuery Waypoints.

Improving the Sticky Scroller

So how do we make the sticky scroller more versatile?
  1. Allow the object to scroll a specified margin from the top of the browser window
  2. Allow the object to begin the scroll effect after the users scrolls a certain amount
  3. Take the starting point of the effect and the ending point of the effect and create a grid of indexes between them
  4. Use these indexes to trigger callbacks that respond to indexes of jQuery ojects

Download with Demo

Download the Zip File (Currently revamping the code, GitHub link will be posted back here soon).

CSS

The only major requirement for CSS is that the scrolling object be absolutely positioned without an absolutely/relatively positioned parent.

Constructor

StickyScroller(obj, options)

obj: The jQuery selector for the object that will be scrolling. Note that only ONE object should be selected. Options: An object containing one or more of the following object members start: At what vertical position of the scrollbar the object will actually begin scrolling (in pixels) end: At what vertical position of the scrollbar the object will stop scrolling (in pixels) margin: How many pixels below the browser window the object will be fixed while scrolling (in pixels) interval: The length of each index (in pixels) range: Length of a range of pixels starting at the top of interval. Convenient for callbacks. This diagram of the demo may help you understand the more abstract options. jQuery Sticky Scroller
Note: "limbo" is the state the scroller is in when it's outside of the range but still within the interval associated with the range. This property isn't set by the developer. It's the calculated difference between the interval and the range. To instantiate a StickyScroller, use the new operator. The call to the StickyScroller class in the demo is:
        var scroller = new StickyScroller("#scrollbox",
        {
            start: 300,
            end: 1800,
            interval: 300,
            range: 100,
            margin: 100
        });
So what you observed was after scrolling down 300px, the sticky scroller effect began by keeping the div "scrollbox" 100px below the top of the browser window. After the initial 300px to initiate the scroller, every 300px scrolled initiates a callback. After scrolling 1800px total, the effect stops and the scrolling object stays put.

Public Methods

Public methods are functions that can be called by instantiations of the StickyScroller class using the dot operator. For the following public function documentations, consider the instantiation of the demo:
        var scroller = new StickyScroller("#scrollbox",
        {
            start: 300,
            end: 1800,
            interval: 300,
            range: 100,
            margin: 100
        });

Accessor Methods

Each option member has an accessor method that returns the property value to the calling environment.
scroller.getStart(); //300
scroller.getEnd(); //1800
scroller.getInterval();//300
scroller.getRange(); //100
scroller.getMargin();//100
Additionally, you can get the current index and previous index
scroller.getIndex();
scroller.getOldIndex();

Callbacks

The callback functions for the StickyScroller work similar to all the callback functions of jQuery you've grown to love, such as .click(). However, instead of passing an anonymous function to the callback, you have the choice to pass current index to the callbacks as well. (Alternatively you could just use scroller.getIndex() in the function body). These callbacks, combined with jQuery's .eq() method (as seen in the demo), can pack quite the UX punch. The callback functions available at this time are:
  • onScroll()
  • onNewIndex()
  • onLimbo()

onScroll(func)

Description: Executes whenever the user scrolls, regardless of position on the screen. Example:
//Will cause an alert every single time the user scrolls. 
//Please don't do this in a real project!
scroller.onScroll(function()
{
     alert("This is rather spammy!");
});

onNewIndex(func)

Description: Executes whenever the user scrolls to a new index. This should be used over onScroll as much as possible. Example:
//Add a class to the div with a class "box" that corresponds to the new index
scroller.onNewIndex(function(index)
{
     $("div.box").eq(index).addClass("active");
});

onLimbo(func)

Description: Executes whenever the user scrolls beyond the range of the current index, but is not yet to the next index. This callback is useful for removing/adding classes to reset a group of elements back to a normal state while the user scrolls to the next index. Example:
//Removes the "active" class from each div with the class of "box"
scroller.onLimbo(function()
{
     $("div.box").removeClass("active");
});

inRange()

Description: Determines if the scroller is in interval range. For more explanation on what the range is, refer to the diagram above. Example:
//Every scroll, see if the scroller is in the range. 
scroller.onScroll(function(index)
{
     //If in range, add the blue class. If not, remove the blue class.
     if(scroller.inRange())
     {
          $("div.box").eq(index).addClass("blue");
     }
     else
     {
          $("div.box").eq(index).removeClass("blue");
     }
});

.distanceFrom(index)

Description: Returns the shortest distance in pixels between the scroller and an index. Example:
//Get the shortest distance in pixels from index 2. 
scroller.distanceFrom(2);

.closestIndex()

Description: Returns the closest index that is not the current index Example:
//Hide the div with class box associated with the closest index
$("div.box").eq(scroller.closestIndex()).hide();

.firstIndex()

Description: Returns the first index (0). This method exists simply for readability purposes. Example:
//Show the first div with class "box"
$("div.box").eq(scroller.firstIndex()).show();

.lastIndex()

Description: Returns the last index. Example:
//Show the last div with class "box"
$("div.box").eq(scroller.lastIndex()).show();

Download

Download the source on GitHub

Notes

The purpose of this plugin, and all my plugins, is to serve as a canvas for your own creativity. Please let me know if there is some limitation in the code that prevents you from realizing your vision.

Jan 8, 2011: Firefox

This effect sucks with Firefox. There's a significant delay in position calculation when switching from position: absolute to position: fixed. Additionally, altering the top value to be $(window).scrollTop() + specified margin yields a really choppy animation in Firefox. If anyone can provide a workaround, that'd be great. December 31, 2010
About the Author:

Joseph is the lead developer of Vert Studios Follow Joseph on Twitter: @Joe_Query
Subscribe to the blog: RSS
Visit Joseph's site: joequery.me