jQuery OS X Style Dock and Stack Navigation

“Outside the Box” Navigation with jQuery

Just about every website uses the regular navigation concepts we’re all used to. After awhile this can get pretty boring, especially for designers who thrive on creativity. While mimicking the OS X dock and stacks isn’t new, it’s certainly not common.


A few days ago, Jeffrey posted about a potential “outside the box” competition on ThemeForest to encourage authors to put on their creativity hats and design usable templates with “outside the box” creative designs. In this tutorial I’ll cover a few ways to do just that with OS X style docks and stacks navigation.

Sources and Credits

Before we get started, I want to give a shout out to a couple guys who came to the rescue when they heard my call for help on Twitter. Steve updated the stacks script by Harley from using jQuery 1.2.6 to use the current 1.3.2 release and Rey Bango from the jQuery team helped me fix a bug. They both jumped to the task within a couple minutes of my cry for help via Twitter. Thanks a ton guys! *Round of applause* :-D

Dock and Stack Preview

Original Sources

Quick Notes

These scripts rely on jQuery 1.3.2. The examples shown are compatible with all major browsers including IE6 and are easy to ensure graceful degrading if JavaScript is off or disabled.

jQuery OS X Dock #1 (Horizontal)

The first dock we’ll build uses the jQuery Fisheye Menu plugin mentioned above. It’s pretty lightweight (~7kb with dependencies) but the main reason I wanted to use this one was because it’s incredibly smooth, no stuttering. View Demo.

jQuery Fisheye Menu Dock

As you can see in the demo, it’s incredibly smooth and responsive. The downside is that you can’t use fixed positioning with it if the page needs to scroll as it will break. If you don’t need it fixed within the browser window then it works great.

This is a great example of “outside the box” concepts in websites and provides an interactive and fun interface.

Required files (I’ve combined the Fisheye plugin and iutil.js in the demo files).

  • jQuery 1.3.2
  • Interface: Fisheye Menu plugin
  • Interface: iutil.js (dependency)

The HTML

We’ll wrap our images and titles in links and place them within a containing div. Then we’ll wrap it all in another containing div for it to function properly.


Notice that I’ve placed the titles in span tags so we can style them as well as allow the plugin to hide/show them as necessary.

The CSS

With CSS we’ll position the dock where we want it on the page. We can’t use fixed positioning with this plugin or it won’t function properly.

.dock-container { position: relative; top: -8px; height: 50px; padding-left: 20px; }
a.dock-item { display: block; width: 50px; position: absolute; bottom: 0; text-align: center; text-decoration: none; color: #333; }
.dock-item span { display: none; padding-left: 20px; }
.dock-item img { border: 0; margin: 5px 10px 0px; width: 100%; }

I’ve also placed a little extra CSS in the head of the page below the CSS included above. I wrapped it in noscript tags in case a visitor doesn’t have JavaScript enabled or available, it will still be a usable navigation. I should point out that this will not validate because the noscript tag isn’t valid in the head section, even though it works in all the current browsers. ;-)

#dock { top: -32px; }
a.dock-item { position: relative; float: left; margin-right: 10px; }
.dock-item span { display: block; }

The JavaScript

We’ll bring in our JavaScript files now starting with jQuery 1.3.2. The fisheye-iutil.min.js file is the combination of the Fisheye plugin and its dependent iutil.js file. We’ll create the last file and put our JavaScript necessary to initialize the dock in it.

%MINIFYHTMLb425fc0027351521e93973809e26c78b9%

Now we’ll initialize the dock once the page loads. You can use several plugin options to customize the dock as you need for positioning and functionality. You can view the documentation by visiting the site listed under sources for the Fisheye plugin.

$(function () { 
	// Dock initialize
	$('#dock').Fisheye(
		{
			maxWidth: 30,
			items: 'a',
			itemsText: 'span',
			container: '.dock-container',
			itemWidth: 50,
			proximity: 60,
			alignment : 'left',
			valign: 'bottom',
			halign : 'center'
		}
	);
});

That’s all there is to it! :-D

jQuery jqDock

jQuery OS X Dock #2 (Vertical)

The horizontal dock was easy and definitely a neat idea to use on websites. They’re probably the most common type used across the web currently so let’s try something different. We could get a little more “outside the box” if we did a vertical dock navigation.

This dock relies on the jqDock jQuery plugin. It’s approximately 10kb in size, so it’s a few kb larger than the previous version but that’s not much. The disadvantage to this plugin is that it’s not quite as smooth as the Fisheye plugin dock, although it’s still very fluid and certainly usable. This plugin also doesn’t have issues with fixed positioning. View Demo.

The HTML

We’ll put our images in an unordered list and wrap them in links. As with the last plugin, we’ll wrap everything within a containing div. When we initialize the plugin we’ll use the “ul” here.

  • Home
  • Contact
  • portfolio
  • music
  • video
  • history
  • calendar
  • links
  • rss
  • rss

You’ll notice on this dock we don’t have titles wrapped in span tags. Instead, this plugin will look at the “title” tag set for each image and create the titles that way (if enabled in the plugin options). This makes the markup a little simpler but it also makes the titles a little less customizable.

The CSS

We position the dock on the left side (can be either side) using fixed positioning. We’ll give it a little space between itself and the top of the browser window for aesthetics and so the icons don’t disappear when enlarged.

#dockContainer { position: fixed; top: 60px; left: 6px; }
#jqDock { position: relative; bottom: 48px; }
.jqDockLabel { background: #333; color: #fff; padding: 3px 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; }

To style the titles we can use the “.jqDockLabel” class. We also won’t need to include any extra styles for it to still be usable with JavaScript disabled. It may not be very pretty but it’s functional.

The JavaScript

We’ll bring in the jQuery library just like the previous dock as well as the plugin.

	

We initialize the dock and set a few options to customize it. You can read the documentation on these settings by visiting the site listed under sources at the beginning of the tutorial for jqDock. What I want to point out here though is the duration option. This is the time for magnification animation in milliseconds. It’s nice to be able to change the duration speed but it seems to get a little stuttery, which is something I hate.

$(function(){
	var jqDockOpts = {align: 'left', duration: 200, labels: 'tc', size: 48, distance: 85};
	$('#jqDock').jqDock(jqDockOpts);
});

You can easily change the positioning of the dock and labels as well as the initial size of the icons and a few other options. What I didn’t like about this plugin is that it magnifies to the full size of the icon. The previous plugin gives you the ability to change the size it magnifies to. That’s all there is to it!

jQuery OS X Stacks Example

jQuery OS X Stack and Drop Stack

This is probably my favorite navigation style out of the three shown in this tutorial. It’s super lightweight (~1kb) and is a really creative “outside the box” method of navigation for a website. It might be a little awkward having the navigation in the bottom right or left of the browser window but it would certainly be creative and save lots of space. View Demo.

While writing this, I realized there are probably many people that won’t like their navigation at the bottom of the page so I took a couple extra minutes and added a drop-down stack to the example files. This way the navigation springs out from top to bottom so it can now be used at the top of pages.
View Demo.

The HTML

The HTML is just as simple as the two dock examples. We’ll place everything in a containing div and place all our images and titles, which are wrapped in links, within an unordered list.


Notice that I’ve placed an image before the unordered list. This is the basket image that the rest of the icons will be stacked behind.

The CSS

We’ll position the main container and make sure the basket image has a higher z-index than the unordered list so everything stacks behind it. Also notice that I’ve given the basket image 35px of padding. This prevents the icons behind the basket from being clicked since the basket image is shorter than the icons. If you change the basket icon to something taller then you’ll need to also change the padding.

.stack { position: fixed; bottom: 28px; right: 40px; }
.stack > img { position: relative; cursor: pointer; padding-top: 35px; z-index: 2; }
.stack ul { list-style: none; position: absolute; top: 5px; cursor: pointer; z-index: 1; }
.stack ul li { position: absolute; }
.stack ul li img { border: 0; }
.stack ul li span { display: none; }
.stack .openStack li span { 
	font-family: "Lucida Grande", Lucida, Verdana, sans-serif;
	display:block;
	height: 14px;
	position:absolute;
	top: 17px;
	right:60px;
	line-height: 14px;
	border: 0;
	background-color:#000;
	padding: 3px 10px;
	border-radius: 10px;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	color: #fcfcfc;
	text-align: center;
	text-shadow: #000 1px 1px 1px;
	opacity: .85;
	filter: alpha(opacity = 85);
}

/* IE Fixes */
.stack { _position: absolute; }
.stack ul { _z-index:-1; _top:-15px; }
.stack ul li { *right:5px; }

The titles wrapped in span tags are set to display:none so they’ll be hidden when the page loads.

The JavaScript

We’ll place the JavaScript in its own file since it’s more than a couple lines. When the image outside the unordered list (the basket) is clicked, it uses jQuery’s toggle function to animate the the list items and set their position based on the horizontal starting point + .75px then multiplied by 2. This gives us the nice curved spring action of the list items.

You could change the .75px or the multiplier (2) to customize how much it curves.

$(function () { 
	// Stack initialize
	var openspeed = 300;
	var closespeed = 300;
	$('.stack>img').toggle(function(){
		var vertical = 0;
		var horizontal = 0;
		var $el=$(this);
		$el.next().children().each(function(){
			$(this).animate({top: '-' + vertical + 'px', left: horizontal + 'px'}, openspeed);
			vertical = vertical + 55;
			horizontal = (horizontal+.75)*2;
		});
		$el.next().animate({top: '-50px', left: '10px'}, openspeed).addClass('openStack')
		   .find('li a>img').animate({width: '50px', marginLeft: '9px'}, openspeed);
		$el.animate({paddingTop: '0'});
	}, function(){
		//reverse above
		var $el=$(this);
		$el.next().removeClass('openStack').children('li').animate({top: '55px', left: '-10px'}, closespeed);
		$el.next().find('li a>img').animate({width: '79px', marginLeft: '0'}, closespeed);
		$el.animate({paddingTop: '35'});
	});
	
	// Stacks additional animation
	$('.stack li a').hover(function(){
		$("img",this).animate({width: '56px'}, 100);
		$("span",this).animate({marginRight: '30px'});
	},function(){
		$("img",this).animate({width: '50px'}, 100);
		$("span",this).animate({marginRight: '0'});
	});
});

Then when the user clicks the basket image again it runs the next function which reverses what we just did. I then added some additional animation to the list items and their titles to give them a little more user feedback, which of course can easily be removed.

And there you have it! A simple and flexible OS X style stack navigation for your website. :-D This script is also in the process of being converted into an easier to use plugin so keep an eye out for that.

Final Thoughts

Hopefully these examples will give you some ideas to be creative and break out of the mold when designing your next website or template. As you can see, jQuery is a powerful library that makes it easy to make our ideas a reality. With a potential upcoming competition based on “outside the box” designs, you might get started on some ideas to submit to ThemeForest. If you haven’t submitted files before, it’s very easy and can definitely be well worth your time! :-)

I want to thank Rey (from the jQuery team) and Steve for answering my call for help on Twitter so quickly. This is a prime example of how useful Twitter can be for designers and developers. If you aren’t following Theme Forest or Nettuts on Twitter yet, now is a good time to do that. They’re both websites with a ton of fantastic information. You can also follow me on Twitter if you’d like.


Tags: jQuery
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Simon

    Damn that’s incredibly nice ! Well at least I now know I don’t have to write it myself as I had decided a few days ago ;)

  • Dave

    awesome effect

  • thomas

    hum… I’m pretty new to webdevelopement and i was wondering how can i put the stack in div. because i wante 3 stack on my website …

  • http://www.TechNation.si Matt

    Very very nice tutorial!

  • http://www.bryanregencia.co BryanRegencia.com – Freelance Web Designer

    Very Nice. Will try that in one of future projects.

  • http://baffleinc.com/ Harley Alexander

    Great to see my code recycled! You did a fantastic job!

  • http://www.springbud.co.uk Shaun Robinson

    A couple of improvements could be made to the stack:

    In the script, line 15, add this:

    height: ’50px’

    Line 21, add this:

    height: ’79px’

    Then in your HTML, specify the height and width of each image.

    This means the images render quicker on page load, and your layout is not messed up if one or more of the images are unavailable.

    • http://www.springbud.co.uk Shaun Robinson

      Oh, and lines 27 and 30 need height added too!

  • http://www.2pxborder.co.nz 2pxborder

    Thanks for sharing, really awesome sutff!

  • Kawsar Ahmad

    its so great work…thanks…i like it :)

  • http://www.stephendurr.com Steve

    Very nice!!

  • ray

    would it be possible to add a rollover effect? perhaps something like the fish eye rollover.

  • ray

    sorry to clarify my previous comment. would it be possible to add a rollover effect to the stacks example?

  • SBosS

    Great job :)

    So, I would like to put vertical dock (example2) on the right side of the screen, how can I do ?

    Thanks

  • http://www.chubweb.com chubweb

    this is so cool, going to embed it in my website

    many thx to you fren :D

  • http://www.iva-is.me Iva

    I have a quick question: are multiple instances of the same type of this menu possible on a single page?

  • http://kartoeglobal.blogspot.com/ bowie

    this posting could be used on the blog???

  • Mike

    Awesome stuff! thanks much for the write up..I’ve been playing around with the stacks navigation and have one tiny problem. My app is using jquery 1.3 at the moment and the stacks-1.js doesn’t want to work with it =P Was wondering if you know how to fix it to work with jquery1.3 instead of 1.3.2 or atleast point me in the right direction to how I could fix the compatability issue =)

    Thanks much!

  • http://www.iwantiphone.co.uk iWantiPhone

    My god, I’m getting left behind. There are so many new techniques that I didn’t know existed. Ok, need to learn it up asap.
    Thanks for the post.

  • Diego

    Hi.. that was nice, but i found an issue when working with masterpages and the icons stay freezed in firefox and IE .In IE it shows “null” is null or not an object…

    Webpage error details
    Message: ‘null’ is null or not an object
    Line: 5 Char: 2 Code: 0
    URI: http://www.adbees.com.br/js/stack.js

    anyone know how to fix it?
    It works fine in regular pages though

  • Diego

    Problem solved.. just put the in the content area and the script worksfine. Hope this helps others..

  • Ding

    Would it be possible to use the stack as a shopping basket?
    For example add an php array in the javascript code

    Thanks for the post.

  • http://www.tl2h.com SBosS

    Great Job :)

    So, I’ve a problem with IE8.

    On my page, I use nick stakenburg Lightivew using scriptaculous and prototype.

    I use jQuery.noConflict(); to solve a problem beetween prototype and jquery dock. It works with prototype 1.6.0.3 but if I use prototype 1.6.1 Rc3 (needed to use Lightview on IE8) It doesn’t work (only on IE8 lightview ok, jqdock ko), all icons are on the same position (left).

    Any idea to fix it ?

    Do you know another dock using scriptaculous or prototype ? Or another lighbox as powerfull as Lightview using jquery ?

    Thanks :)

  • JP

    Firstly, awesome script man. Just what I’ve been looking for!

    However, I have one problem. This script uses Div tags. The site I have been designing uses standard tags and it’s hierarchies. Still pretty green to all of this.

    How can I implement this into a table data tag or something within my site without completely breaking the whole thing?

  • http://joeldt.net Joel

    This is nice—really, really nice—but it occurred to me that you didn’t add a .stop to the dropdown stack animation, so if you hover over one icon several times in succession, the caption animation will “stack up” rather than cancel each time. This would certainly be a helpful addition, and it looks cleaner as well.

  • http://qtrworld.com qatar world

    wow .. pretty awesome

  • http://www.cluzeauwebdesign.com Julien

    Hi, I used the horizontal dock menu navigation as a bottom menu for my web site http://www.cluzeauwebdesign.com .Thanks a lot for this tut and for the plugin!

  • http://www.isotools.com Jean-Marc

    Hi,
    I intend to use the second menu for our web site http://www.isotools.com
    Where can I buy the icons displayed in your demo ?

    Many thanks,
    J.M.

  • http://htinnervoice.blogspot.com/ jolly

    not working plz help :( where to put j.s . i am trying it on blogger

  • http://www.jquerymagic.com Mahbub

    I’ve just loving this. Can’t wait to implement in some projects.

  • Rubin Geo Varghese

    i would like to change the horizontal/vertical fisheye menu to a rotating circular fisheye menu ,,what should i do?

  • http://www.dev-hq.co.uk Joe

    I might use this in a future project!

  • jorge

    Hi,
    Nice script.
    Can you send the code for the icons fall from the basket onmouseover, insted onclick?
    Thanks

  • http://www.vijayakumar.org Vijaya Kumar S

    Nice work.. Really great stuff and excellent explanation.

  • http://9laps.com Brian Miller

    I had an idea for implementing this the other day as I was brainstorming a new layout. I’d like to implement for a long list of songs with a “play” button next to the text that expands as you hover and the spacing between the expands with it (maybe even enlarge the font).

    However I’m a jquery noob so it may take me a while to modify this .js. Anyone interested in taking this on?

  • http://team1504.com Irfan

    Could someone help me with this?

    Im pretty sure i did everything fine, but it is not working..
    To be concise, my mouse changes to a click when i hover over the images, but when i click on the icons or the stack-try nothing happens….
    Here is a screenshot of what the file looks like opened in firefox.
    http://screencast.com/t/MzdmZTViMWYt

    I have pasted my code here (all it is is the stack nothing else) :
    http://pastebin.com/f8a1bfc4

    ** My code links to a javascript file like the tutorial said i should, it is here:
    http://pastebin.com/f57b969fc

    I hope someone can help me with this because I told me teacher I would do this and he expect it on his site– making it is my homework.

    P.S Here is a video of me trying to use it
    http://screencast.com/t/YmUwZDg2OWU

    Dont worry about the link to index.html not working. there is no index.html in that directory. I just want the stack feature to work.

  • http://skinbox.net Olivier Turbis

    Incredible. Thanks so much for sharing this.

  • http://manuelrocha.info Manuel

    That’s nice! I’ll try to apply to some future projects :) thanks!!

  • http://www.optimum7.com Jorge

    This is a really cool and fun way to add interactivity.

  • woetoen

    Hi, thanks for sharing, i have a question, is it possible to add sub menu in it?

  • tperkins

    Hey great job on this.

    One thing I noticed that others might have mentioned.

    When you hover over all the buttons quickly, the sub menus stack over each other.

    This can be fixed by adding:
    $(“.sub-links”).stop(true,true);

    Right before:
    $(“.sub-links”).hide();

    It will stop the previous fade-in or any ‘queued’ fade-ins.

    • tperkins

      I apoligize, I thought I was looking at the comments for another tutorial. my bad.

  • gordack

    Hi, great script.
    Could you please add horizontal version of stack ? and how can I make it always open ?

  • http://russianpenguin.ru S7a1k3r

    Very nice plugin. It is possible to add stack element for horizontal or vertical menu? (Like OSX dock)

  • M

    in your demo, I noticed that the upside down Stack and Drop Stack has some weird behavior. once all the icons are stacked inside the basket, if i move around the cursor over the basket it sometimes shrinks all the icons.. is this a bug?

    i’m on chrome/windows btw

  • http://www.namakusurya.com Surya Adi Sapoetra

    great tutorial, i really like it.. thanks.

  • sukma

    wow amazing!!!!…very nice tutorial.

    i am newbie on editing blog, can you help me

    where do i put the HTML code , CSS code, java script code.
    after ….or before ][….

    please detail explaination.thank you
    morning_bl@yahoo.com

  • CJ

    Has anyone tried to combine these two scripts? More or less having the OSX Dock with the menus that pop out when clicked on. I have started to make this work but the items cause a large gap between the icons. Any ideas?

  • http://artbyjb.com/ Jeffrey Bennett

    Hi there! I’d love to see this work, but it seems to be broken. Is there any way you could fix it and let me know when it’s available again? Thank you!

    P.S. I’m using Mozilla Firefox 3.6.3 on Windows 7, just in case you need to know. :)

    • http://artbyjb.com/ Jeffrey Bennett

      OK, don’t mind me. I forgot that I had JavaScript disabled for user testing… Time to get some coffee! LOL!

      It works great when JavaScript is ON. :)

  • http://www.vishnuvalentino.com Valentino

    It is awesome mate!!

  • http://123doing.com 123doing

    It’s very good.
    I like this.
    Thanks for share.
    And I wrote something to introduce this project for my readers.
    You can find the post about this in my website.
    If something is wrong,pls figure it out.thanks.

  • Thomas

    Is this compatible with jQuery v1.4.x? Or do you have to stick to jQuery 1.3.x?