While building out a content management system for DMP I needed to create a toolbar which would stay with position: fixed; on the y-axis, but act like position: absolute on the x-axis. To achieve this I used a clever JavaScript class from David Walsh called scrollspy.

The JavaScript
Things you will need first: Mootools (This demo uses 1.2.4) and the ScrollSpy plugin from David Walsh. Next write this for you element:
var ss = new ScrollSpy({
mode: 'horizontal',
onTick: function(position,state,enters,leaves) {
$("sidePanel").style.left = -position.x+"px";
},
container: window
});
The CSS
In the CSS use position: fixed; because we have handled the position-x: absolute; in JavaScript. so:
#sidePanel {
position:fixed;
left:0;
top:0;
width:250px;
z-index:1000;
}
The above example will keep our sidePanel element from disappearing when you scroll down the page but it will scroll with the page when the user scrolls right.
To do the opposite ie. position-x: fixed; position-y: absolute; In the JavaScript change mode: ‘horizontal’ to mode: ‘vertical’ and -position.x+”px”; to -position.y+”px”; and that’s it any comments, ideas or improvements leave them below.
Thanks alot, this quick tutorial saved my day! (:
Hey man no worries.
I’ve used this code so many time (^_^)
Hey Ricky,
I found this tutorial while searching how to have a fixed sidebar vertically but not horizontally, like the sidePanel you have on this site.
I’ve run into one problem that I can’t seem to figure out though. Everything works perfectly, the x-axis is position:absolute and the y-axis is fixed, but when I make the window small enough to scroll horizontally, and scroll so that the sidebar is out of the screen, and then maximize the window, the sidebar is still out of the screen (now with no horizontal scroll).
This website here doesn’t do that, everything pops right back into place when I maximize here, so I was wondering if you could tell me how to fix that.
Thanks a bunch.
Hi Ricky!
I get an error in the console, telling me style.left is undefined. wtf?
In my demo or your own? Cos I can’t replicate the error here. (firefox/firebug).
I *love* this demo, but I’m having trouble getting it to work. I’m pretty good with html and css, but I have no javascript experience. I can’t even figure out if I’m supposed to put MooTools and ScrollSpy in the head, in the body, or in a linked file! Could you point me to a dummies guide on how to use this awesome stuff?
Thanks,
Meg
Hi Meg,
David Walsh has updated his plugin for a newer version of mootools. I used this version of scroll spy:
var ScrollSpy = new Class({
/* implements */
Implements: [Options,Events],
/* options */
options: {
min: 0,
mode: ‘vertical’,
max: 0,
container: window,
onEnter: $empty,
onLeave: $empty,
onTick: $empty
},
/* initialization */
initialize: function(options) {
/* set options */
this.setOptions(options);
this.container = $(this.options.container);
this.enters = this.leaves = 0;
this.max = this.options.max;
/* fix max */
if(this.max == 0)
{
var ss = this.container.getScrollSize();
this.max = this.options.mode == ‘vertical’ ? ss.y : ss.x;
}
/* make it happen */
this.addListener();
},
/* a method that does whatever you want */
addListener: function() {
/* state trackers */
this.inside = false;
this.container.addEvent(‘scroll’,function() {
/* if it has reached the level */
var position = this.container.getScroll();
var xy = this.options.mode == ‘vertical’ ? position.y : position.x;
/* if we reach the minimum and are still below the max… */
if(xy >= this.options.min && xy <= this.max) {
/* trigger Enter event if necessary */
if(!this.inside) {
/* record as inside */
this.inside = true;
this.enters++;
/* fire enter event */
this.fireEvent(‘enter’,[position,this.enters]);
}
/* trigger the “tick”, always */
this.fireEvent(‘tick’,[position,this.inside,this.enters,this.leaves]);
}
else {
/* trigger leave */
if(this.inside)
{
this.inside = false;
this.leaves++;
this.fireEvent(‘leave’,[position,this.leaves]);
}
}
}.bind(this));
}
});
Hey Ricky,
The demo you have is awesome, but I cannot get it to work. I’ve copied the javascript you posted in the earlier comment, saved it as ScrollSpy.js, and still nothing. I also tried copying the source of your demo example and using that, but that doesn’t work either. I’d really like to get this working because it seems like easily the best fix anywhere on the internet that I can find.
Basically what I’d like to know is this: What isn’t displayed in the source of the demo page? I feel like thats probably the key to whatever I have that isn’t working.
As an update, I figured out what my problem was. The jquery library does not seem to play nicely with mootools, so ensure that you’re not including both if you want to avoid an hour of frustration.
Great tutorial, thanks!
Sorry man your demo is cool but your explaination is defintely too brief and lacks of some fundamental details; your code in demoMain is quite different, that’s why the demo works!
Oh man I should have looked for this years ago! Thanks for the knowledge!
Looks great and is exactly the problem I would like to solve, i.e. fixed x and absolute y pos., but I am not experienced enough to use your code. I want to scroll a widget element in WP Theme Weaver. Any directions how and whether your solution can be applied are very much appreciated.
Hi Ricky,
The demo is so nice and its working fine in IE browser and the events of rad grid control also fired, but in firefox and chrome rad grid control events are not fired. please suggest me is their any modification to work in firefox and chrome.
Thanks.
This looks nice – but as my project is depending on jQuery: Is there an alternative method without Mootools?
I’m trying to integrate with jQuery, I’ve tried 1.4 w/out luck. When I link the jQuery Lib none move in the allowed direction. Do you know if this is compatible with other versions of jQuery?
Thanks
PD