Advertisement

"Outside the Box" Navigation with jQuery

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

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.

<div id="dock">
	<div class="dock-container">
		<a class="dock-item" href="index.html"><span>Example 1</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/home.png" alt="home" /></a> 
		<a class="dock-item" href="example2.html"><span>Example 2</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/email.png" alt="contact" /></a> 
		<a class="dock-item" href="example3.html"><span>Example 3</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/portfolio.png" alt="portfolio" /></a> 
		<a class="dock-item" href="all-examples.html"><span>All Examples</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/music.png" alt="music" /></a> 
		<a class="dock-item" href="#"><span>Video</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/video.png" alt="video" /></a> 
		<a class="dock-item" href="#"><span>History</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/history.png" alt="history" /></a> 
		<a class="dock-item" href="#"><span>Calendar</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/calendar.png" alt="calendar" /></a> 
		<a class="dock-item" href="#"><span>Links</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/link.png" alt="links" /></a> 
		<a class="dock-item" href="#"><span>RSS</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/rss.png" alt="rss" /></a> 
		<a class="dock-item" href="#"><span>RSS2</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/rss2.png" alt="rss" /></a> 
	</div><!-- end div .dock-container -->
</div><!-- end div .dock #dock -->

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.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="js/fisheye-iutil.min.js"></script>

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.

<div id="dockContainer">
	<ul id="jqDock">
		<li><a class="dockItem" href="index.html"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/home-sm.png" alt="Home" title="Example 1" /></a></li>
		<li><a class="dockItem" href="example2.html"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/email-sm.png" alt="Contact" title="Example 2" /></a></li>
		<li><a class="dockItem" href="example3.html"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/portfolio-sm.png" alt="portfolio" title="Example 3" /></a></li>
		<li><a class="dockItem" href="all-examples.html"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/music-sm.png" alt="music" title="All Examples" /></a></li>
		<li><a class="dockItem" href="#"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/video-sm.png" alt="video" title="Video" /></a></li>
		<li><a class="dockItem" href="#"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/history-sm.png" alt="history" title="History" /></a></li>
		<li><a class="dockItem" href="#"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/calendar-sm.png" alt="calendar" title="Calendar" /></a></li>
		<li><a class="dockItem" href="#"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/link-sm.png" alt="links" title="Links" /></a></li>
		<li><a class="dockItem" href="#"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/rss-sm.png" alt="rss" title="RSS" /></a></li>
		<li><a class="dockItem" href="#"><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/dock/rss2-sm.png" alt="rss" title="RSS" /></a></li>
	</ul>
</div><!-- end div #dockContainer -->

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.

	<script type="text/javascript" src="js/jquery.jqDock.min.js"></script>

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.

<div class="stack">
	<img src="http://nettuts.s3.amazonaws.com/358_jquery/images/stacks/stack.png" alt="stack" />
	<ul id="stack">
		<li><a href=""><span>Aperture</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/stacks/aperture.png" alt="Aperature" /></a></li>
		<li><a href="#"><span>All Examples</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/stacks/photoshop.png" alt="Photoshop" /></a></li>
		<li><a href="example3.html"><span>Example 3</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/stacks/safari.png" alt="Safari" /></a></li>
		<li><a href="example2.html"><span>Example 2</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/stacks/coda.png" alt="Coda" /></a></li>
		<li><a href="index.html"><span>Example 1</span><img src="http://nettuts.s3.amazonaws.com/358_jquery/images/stacks/finder.png" alt="Finder" /></a></li>			
	</ul>
</div><!-- end div .stack -->

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.


Advertisement