Treehouse

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!

ydkjs-6.png

Recent Features

  • 9 Mind-Blowing WebGL&nbsp;Demos

    As much as developers now loathe Flash, we're still playing a bit of catch up to natively duplicate the animation capabilities that Adobe's old technology provided us.  Of course we have canvas, an awesome technology, one which I highlighted 9 mind-blowing demos.  Another technology available...

  • Create a CSS&nbsp;Cube

    CSS cubes really showcase what CSS has become over the years, evolving from simple color and dimension directives to a language capable of creating deep, creative visuals.  Add animation and you've got something really neat.  Unfortunately each CSS cube tutorial I've read is a bit...

Incredible Demos

  • CSS Animations Between Media&nbsp;Queries

    CSS animations are right up there with sliced bread. CSS animations are efficient because they can be hardware accelerated, they require no JavaScript overhead, and they are composed of very little CSS code. Quite often we add CSS transforms to elements via CSS during...

  • HTML5&#8217;s placeholder&nbsp;Attribute

    HTML5 has introduced many features to the browser;  some HTML-based, some in the form of JavaScript APIs, but all of them useful.  One of my favorites if the introduction of the placeholder attribute to INPUT elements.  The placeholder attribute shows text in a field until the...

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!