O'Reilly

Introducing MooTools ScrollSidebar

By on  
Side ScrollBar

How many times are you putting together a HTML navigation block or utility block of elements that you wish could be seen everywhere on a page? I've created a solution that will seamlessly allow you to do so: ScrollSidebar. ScrollSidebar allows you to attach an element to a place on the screen and animate the menu to the current scroll position.

The HTML

<div id="sidebar-menu">
	<ul>
		<li><a href="#pagetop" id="sidebar-menu-top" title="Top of Page" style="background:url(menu-up-arrow.png) center center no-repeat;">Top of Page</a></li>
		<li><a href="/" style="background:url(menu-home.png) center center no-repeat;" title="Go to the Homepage">Homepage</a></li>
		<li><a href="http://twitter.com/home?status=I love David Walsh's blog!  MooTools, CSS, jQuery, PHP...it has everything!" id="sidebar-menu-twitter" style="background:url(menu-twitter.png) center center no-repeat;" title="Share on Twitter">Post on Twitter</a></li>
		<li><a href="#pagebottom" id="sidebar-menu-bottom" style="background:url(menu-down-arrow.png) center center no-repeat;" title="Bottom of Page">Bottom of Page</a></li>
	</ul>
</div>

You may code the menu's HTML any way you'd like. For the sake of accessibility and semantics (I literally just shivered at the thought of following semantics) I've used an HTML list.

The CSS

#sidebar-menu	{ display:none; width:48px; background:#333; border:1px solid #000; padding:10px; -webkit-border-radius:10px; -moz-border-radius:10px; }
#sidebar-menu ul{ padding:0; list-style-type:none; }
#sidebar-menu a	{ color:#fff; display:block; height:48px; width:48px; text-indent:-3000px; overflow:hidden; }

You may code the sidebar menu any way you'd like too. No need to worry about positioning the menu though -- the plugin will override that anyway. I highly recommend addressing the menu's width. I'm also defaulting the menu to display:none until the menu can be positioned.

The MooTools JavaScript

var ScrollSidebar = new Class({
	
	Implements: [Options],
	
	options: {
		offsets: { x:0, y:0 },
		mode: 'vertical',
		positionVertical: 'top',
		positionHorizontal: 'right',
		speed: 400
	},
	
	initialize: function(menu,options) {
		/* initial options */
		this.setOptions(options);
		this.menu = $(menu);
		this.move = this.options.mode == 'vertical' ? 'y' : 'x';
		this.property = this.move == 'y' ? 'positionVertical' : 'positionHorizontal';
		/* ensure a few things */
		var css = { position: 'absolute', display:'block' };
		css[this.options.positionVertical] = this.options.offsets.y;
		css[this.options.positionHorizontal] = this.options.offsets.x;
		this.menu.setStyles(css).set('tween',{ duration: this.options.speed });
		/* start listening */
		this.startListeners();
	},
	
	startListeners: function() {
		var action = function() {
			this.setPosition($(document.body).getScroll()[this.move] + this.options.offsets[this.move]);
		}.bind(this);
		window.addEvent('scroll',action);
		window.addEvent('load',action);
	},
	
	setPosition: function(move) {
		this.menu.tween(this.options[this.property],move);
		return this;
	}
});

/* usage */
window.addEvent('domready',function() {
	$('sidebar-menu').set('opacity',0.8); //opacity effect for fun
	var sidebar = new ScrollSidebar('sidebar-menu',{
		offsets: {
			x: 20,
			y: 20
		}
	});
});

I wont bore you with the parameter/option descriptions as they're self-explanatory. I've kept the class very simple. For those who care to see what the functionality looked like pre-Class, here you go:

//paired with smooooothscroll
new SmoothScroll({ duration:300 });
//vars
var menu = $('sidebar-menu'), offsetY = 20, offsetX = 20, speed = 450;
var setPosition = function(top) {
	var scroll = $(document.body).getScroll();
	menu.tween('top',scroll.y + offsetY);
};
//settings
menu.set('tween',{ duration: speed }).setStyles({
	position: 'absolute',
	right: offsetX,
	top: offsetY,
	opacity: 0.8
});
//events
window.addEvents({
	scroll: setPosition,
	load: setPosition
});

As you can probably tell, the functionality was begging to be placed into plugin format.

Have any feature suggestions? Share them. If you're looking for a sweet jQuery version, please head over to CSS-Tricks to see Chris Coyier's take!

Track.js Error Reporting

Recent Features

  • Regular Expressions for the Rest of Us

    Sooner or later you’ll run across a regular expression. With their cryptic syntax, confusing documentation and massive learning curve, most developers settle for copying and pasting them from StackOverflow and hoping they work. But what if you could decode regular expressions and harness their power? In...

  • Create a Sheen Logo Effect with CSS

    I was inspired when I first saw Addy Osmani's original ShineTime blog post.  The hover sheen effect is simple but awesome.  When I started my blog redesign, I really wanted to use a sheen effect with my logo.  Using two HTML elements and...

Incredible Demos

  • Implement jQuery&#8217;s hover() Method in MooTools

    jQuery offers a quick event shortcut method called hover that accepts two functions that represent mouseover and mouseout actions. Here's how to implement that for MooTools Elements. The MooTools JavaScript We implement hover() which accepts to functions; one will be called on mouseenter and the other...

  • TextboxList for MooTools and jQuery by Guillermo Rauch

    I'll be honest with you: I still haven't figured out if I like my MooTools teammate Guillermo Rauch. He's got a lot stacked up against him. He's from Argentina so I get IM'ed about 10 times a day about how great Lionel...

Discussion

  1. Nicely done! I might find a use for that someday.

    That kinda reminds me of the “top of page” link that appears only when detecting that the user had scrolled farther then X pixel down… what was the name… ah! ScrollSpy (http://davidwalsh.name/js/scrollspy)!

  2. kolin

    nah, not a fan of these kind of things, i find them slightly annoying, in that ‘go away’ fashion reminicent of late 90’s “congratulations, you’re our millionth visitor, you’ve won an ipod FLASH FLASH FLASH” popups that follow you everywhere.

  3. Not a fan of these “replacements”. Especially not this one since each click works like a new page in firefox and makes you click the back button the same amount of times you’ve used the scroll-sidebar.

  4. Great stuff.

    Is there a reason you don’t cache $(document.body) instead of “grapping” it ever time there’s a scroll event?

    @kolin – Like all design, implementation is key. I agree that tweening does have that “FLASH FLASH FLASH!!” feeling, I prefer to just set the position as though it’s CSS is fixed. And so I’ll take this class, and implement my own setPosition method.

  5. @kolin: Hahah, true. That’s why I may not use it in public website, where the uses are limited (#top, #bottom, twitter, contact… but that’s pretty much all) but more into an admin panel or specific site where tools could be needed (Deleting stuff such as pictures, posts, comments; switching style; dragging tools; purchase carts…).

  6. not a fan at all of the scrolling effect. Why are you using javascript at all to keep it positioned? It makes it choopy, and in my mind, very unprofessional looking
    What’s wrong plain old CSS? In fact, the whole thing could be done completely in CSS and be just as nice. The only thing you need Javascript for would be to make it scroll up/down, instead of jump up/down to the links

  7. @kolin: No way! The first thing i thought of was of the 90’s mouse chasers. I have seen this effect used well for login boxes before though. on page resize it was used to keep the box in the center at all times.

  8. Louis W

    Why would I want to instantly scroll to the bottom of the page? It would make much more sense to just scroll down the distance of the viewport (page down).

    Also, I find the fact that the navigation element animates down after it scrolls a bit strange. Personally I would prefer if it were always fixed in the same position and never scrolled.

  9. Whoa — I didn’t expect so many people to be drinking the haterade on this one. I think it’s very tasteful. My example would be too big for a production site but I needed it to be noticeable for the sake of the example.

    And saying it’s the same as a mouse-chaser is nuts!

  10. I fail to see the need for a ‘scroll to bottom’ button, but I think the concept is a useful one. Maybe I would remove the animation. Maybe I would scale it down. Maybe I would stick a login box in there, or a shopping cart (as has been suggested), but I certainly won’t be having kittens over this lovely piece of code David has written for mass general consumption.

    Good job Mr Walsh!

  11. Yeah, I guess im not really a fan of these either.

    But… David, if you could figure out a way to make a the browser back buttons scroll back the position it was at, you would have a winner.

    @Marcus If you want to not store all the anchors in the history (but still want them for bookmark purposes) you can use document.location.replace, but it wont work in webkit browsers(still adds a history item).

  12. Q_the_Novice

    I agree with the consensus, this is the type of scroll that gives you the same feeling as your psycho ex – it just wont leave u alone!!!

  13. The-F

    Nice!
    Is there anyway to make the scroller start after some defined height or stop after some defined position?
    Sample (Mootools v1.1): http://demo.gavick.com/joomla15/nov2009/

  14. excellent work dude!!!!

    Thanks

  15. Hi David,
    Thanks alot for this cute scroller class.
    I used it.
    I had a main question about Mootools (or Javascript) which I found it again in your code:

    initialize: function(menu, options) {
    	/* initial options */
    	this.setOptions(options);
    	this.menu = $(menu);	
    }

    In initialize function you set this.menu with a reference to menu element. I want to know if this is a performance issue or not?
    I usually use element id instead of element reference, and when I need it use $ function to get element.
    Which is better? use $ function one time and store a reference to element in class or store a string (id) and then use $ function whenever you need it?

    BTW: I read an article about javascript garbage collection a few month ago, and there, he said about DOM element references and events and confusing browsers garbage collection method.

    This is a question which conflicts me! Help me please.

    Thank you.

  16. Valentina

    Hello,
    i have a question, could you help me, please?
    I’d need to stop this menu at bottom of the page, before of footer.
    Could you tell me the java code to do it?
    Thank you so much

  17. Dave

    Any suggestions how I can use this to have it float over a table?

    Thanks

  18. Yah I’ve been looking for a script like this that can be told to stop at a certain point – most likely at some distance from the top or from the bottom. How easy would it be to add that to the script?

  19. bill

    can i install joomla website if yes how
    thanks

  20. Basta

    Can i change the position of the bar to positionate it horizentaly?? Could anyone help me to do it?
    Thanks

  21. This is really cool. I want to use it to place a mini-chatroom that is constantly floating. However, I need to let users have the option to close/open the floating bar at will. So for example when a user clicks “close” the entire bar will be reduced or collapsed into a bar that says “open” or something like that. PLEASE PLEASE can you tell me how to or please add that to the script? Thanks

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Making Data Management Easy with Transpose

    One problem with data collection is that we all want capture to be quick and we all want data to be organized -- but there's seldom a utility that allows both. Evernote allows note-taking but it can lose its structure...and no one wants...

  • Serve a Directory via Python

    Sometimes I'm working with a test HTML file and some JavaScript but need to work off of a served space.  In that case, I sometimes need to swap out folders within MAMP Stack which leads to a maintenance nightmare.  Bleh. I recently found out that you can...

  • OSCON Portland:  Conference  Discount!

    O'Reilly puts on the best web industry conferences in the world.  These conferences include Fluent Conference, Velocity Conference, and the upcoming OSCON in Portland, Oregon from July 20-24.  Open Source Convention (OSCON) is a conference that focuses specifically on open source developers and the tools and possibilities...

  • Follow Redirects with cURL

    I love playing around with cURL. There's something about loading websites via command line that makes me feel like some type of smug hacker, just like tweeting from command line does. I recently cURL'd the Google homepage and saw the following: I found it weird that Google...

  • Developers Have WordPress, Amateurs Have Squarespace, Professional Designers Have the NEW Webydo!

    Web design platforms have traditionally come in one of two varieties. There are the solutions like WordPress and Drupal that are incredibly powerful, but an understanding of web development and coding is required to be able to use those platforms effectively. On the other side of the...