How To Unobtrusively Scroll A Div With Prototype & Scriptaculous
Hot Demo
Nothing beats a good demo of what you can do with these extensions to prototype/scriptaculous.
Hot Div Scrolling
Prototype/Scriptaculous Div Scrolling Effect
Hot Window Scrolling
Prototype/Scriptaculous Window Scrolling Effect
Both examples use position of element anchors on the page. The examples also use page anchors that update in the URL once the scroll effect has finished. This means that if you scroll to a part of the page and send the url to someone else who doesn’t have JS enabled they’ll still see the same page content.
Why not use Control.Scroller?
I really enjoy having minute control of things on my user interface but I’m always reminded that I have to find solutions that degrades elegantly mostly because of SEO considerations but also because Aunt Tilly might not have upgraded yet.
Though you can figure out whether a user scrolls the mouse with Javascript you don’t have access to the operating system’s preference in regards to scrolling speed. I don’t like guessing because people have wildly different preferences.
In order to please the user I recommend that you leave him with what he’s used to but only use Javascript to enhance the experience he’s already familiar with. That way you don’t frustrate him with unexpected behavior but offer him extras.
How To Scroll A Div: A Primer
In order for a div to have a scroll bar you must set the height(at least for Safari to be happy) and you must set its overflow value to ‘auto’ or ’scroll’. In most cases ‘auto’ lets your elements flow vertically and horizontally in such a way that you should normally be left with only a vertical scrollbar.
window.scrollTo already exists and allows all browser since 4.0 era to scroll to arbitrary left and top positions on the page. The homonymous method on Element (Element.scrollTo) does not act the same way. When you call it on an element the page will call window.scrollTo with to display the element at the top right of the viewport. Really handy but not exactly what I wanted.
What I did want was to have a scrollTo method that acted the same way as window.scrollTo but on divs.
So I wrote this little bit of code:
Element.addMethods({
scrollTo: function(element, left, top){
var element = $(element);
if (arguments.length == 1){
var pos = element.cumulativeOffset();
window.scrollTo(pos[0], pos[1]);
} else {
element.scrollLeft = left;
element.scrollTop = top;
}
return element;
}
});
This piece of code doesn’t break the current Element.scrollTo method but adds the possibility to offer left/top values on call.
I also wanted to see if I couldn’t get a nice scrolling effect so I wrote a new effect for Scriptaculous.
Effect.Scroll Scriptaculous Enhanced Div Scrolling
Effect.Scroll = Class.create();
Object.extend(Object.extend(Effect.Scroll.prototype, Effect.Base.prototype), {
initialize: function(element) {
this.element = $(element);
if(!this.element) throw(Effect._elementDoesNotExistError);
this.start(Object.extend({x: 0, y: 0}, arguments[1] || {}));
},
setup: function() {
var scrollOffsets = (this.element == window)
? document.viewport.getScrollOffsets()
: Element._returnOffset(this.element.scrollLeft, this.element.scrollTop) ;
this.originalScrollLeft = scrollOffsets.left;
this.originalScrollTop = scrollOffsets.top;
},
update: function(pos) {
this.element.scrollTo(Math.round(this.options.x * pos + this.originalScrollLeft), Math.round(this.options.y * pos + this.originalScrollTop));
}
});
For those unfamiliar with Scriptaculous effects the initialize, setup and update methods are part of any effect you would create. They’re pretty straightforward so I won’t spend too much time with them unless someone has questions.

on November 28th, 2007 at 5:20 pm
Super awesome! This is exactly what I’ve been looking for, thanks a ton!
on December 21st, 2007 at 3:58 pm
Thank you very much! Just what I was looking for.
on January 8th, 2008 at 3:47 pm
Great Script! Works like a champ and very easy to implement.
on February 28th, 2008 at 7:10 pm
Looks great… but I can’t figure out how to include the JS code you’ve created. I’ve included the addMethods you have in both effects.js and prototype.js, and I’ve included Effect.Scroll in a separate file (effect.scroll.js) which is read in like effect.js and prototype.js. However, it doesn’t do smooth scrolling - just jumping. What am I doing wrong?!
on February 28th, 2008 at 11:57 pm
@phub11:
add handlers with something akin to:
You can check it out in the example here.
on March 25th, 2008 at 11:50 am
Does this script works with horizontal scrolling? Thank you.
on April 15th, 2008 at 5:23 am
Great piece of code, and it works flawlessly in paragraphs. Only that I realized the scrolling effect doesn’t happen when you put the target anchor in another nested further down the page like in the example below. Am I missing something?
Link1
on April 16th, 2008 at 8:48 am
Hi,
I was wondering is it possible to use that script that just scrolls by pixels and not anchors?
I’ve just started looking at Prototype & Scriptaculous so excuse my ignorance.
thanks
on June 3rd, 2008 at 9:51 am
Hello Gary
This is what I’m searching for …
Love and happiness should be the way you walking.
Greetings from good old Germany