O'Reilly

Create Snook-Style Navigation Using MooTools

By on  

Jonathan Snook debuted a great tutorial last September detailing how you can use an image and a few jQuery techniques to create a slick mouseover effect. I revisited his article and ported its two most impressive effects to MooTools.

The Images

Image 1 Image 1

These are the same images used in Snook's article.

The XHTML

<h2>Example 0: No Script</h2>
<ul id="noscript">
	<li><a href="#">Home</a></li>
	<li><a href="#">About</a></li>
	<li><a href="#">Contact</a></li>
</ul>

<h2>Example A: Top down</h2>
<ul id="a">
	<li><a href="#">Home</a></li>
	<li><a href="#">About</a></li>
	<li><a href="#">Contact</a></li>
</ul>

<h2>Example B: Right left</h2>
<ul id="b">
	<li><a href="#">Home</a></li>
	<li><a href="#">About</a></li>
	<li><a href="#">Contact</a></li>
</ul>

Three menus. The first will be a simple CSS-only mouseover, the other two will be varying MooTools versions.

The CSS

ul { list-style:none; margin:0; padding:0; }
li { float:left; width:100px; margin:0; padding:0; text-align:center; }
li a { display:block; padding:5px 10px; height:100%; color:#fff; text-decoration:none; border-right:1px solid #fff; }
li a { background:url(snook-animation-bg2.jpg) repeat 0 0; }
a:hover, a:focus, a:active { background-position:-150px 0; }
#a a { background:url(snook-animation-bg.jpg) repeat; background-position:-20px 35px; }
#b a { background:url(snook-animation-bg2.jpg) repeat; background-position:0 0; }

Nothing too notable here.

The MooTools JavaScript

window.addEvent('domready', function() {
	/* example a:  top down */
	$$('#a a').each(function(el) {
		//fx
		var fx = new Fx.Tween(el,{
			duration: 500,
			link: 'cancel'
		});
		
		//css & events
		el.setStyle('background-position','-20px 35px').addEvents({
			'mouseenter': function(e) {
				e.stop();
				fx.start('background-position','-20px 94px');
			},
			'mouseleave': function(e) {
				e.stop();
				fx.start('background-position','-20px 35px');
			}
		});
	});
	
	/* example b:  right left */
	$$('#b a').each(function(el) {
		//css
		var reset = false;
		var fx = new Fx.Tween(el,{
			duration: 500,
			link: 'cancel',
			onComplete:function() {
				if(reset) {
					el.setStyle('background-position','0 0');
				}
			}
		});
		//events
		el.setStyle('background-position','0 0').addEvents({
			'mouseenter': function(e) {
				e.stop();
				fx.start('background-position','-150px 0');
				reset = false;
			},
			'mouseleave': function(e) {
				reset = true;
				fx.start('background-position','-300px 0');
			}
		});
	});
	
});

When you mouseover the last two navigation menu links, the background image animates from one spot to another creating a flash-like effect.

Credit goes to Snook for this great idea and original execution.

O'Reilly Velocity Conference
Save 20% with discount code AFF20

Recent Features

  • LightFace:  Facebook Lightbox for MooTools

    One of the web components I've always loved has been Facebook's modal dialog.  This "lightbox" isn't like others:  no dark overlay, no obnoxious animating to size, and it doesn't try to do "too much."  With Facebook's dialog in mind, I've created LightFace:  a Facebook lightbox...

  • Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API,...

Incredible Demos

  • Sexy Album Art with MooTools or jQuery

    The way that album information displays is usually insanely boring. Music is supposed to be fun and moving, right? Luckily MooTools and jQuery allow us to communicate that creativity on the web. The XHTML A few structure DIVs and the album information. The CSS The CSS...

  • HTML5&#8217;s placeholder 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. Great tutorial, thanks! I love being able to use Javascript to create animations which people think can only be done using flash. This particular example is one of my favourites.

  2. olivier

    the horizontal mode produces a really nice effect when moving cursor from one button to another.

  3. wow…. this is great.. i like the second demo… it’s very funny :)

  4. Jem

    This example seems pretty useful if you have something a bit more abstract for a background. The “oozing” effect you get by tween the background-position is quite cool.

    I recently saw an article here where they had ported over a jquery effect someone had created for working with sprites into mootools. Also useful.

  5. I like example B when moving right to left as it looks like it is shifting. Is there a way to detect the user coming from a left side button going right and have it switch the direction?

  6. Alelo

    should be doable, if u make geht the mouse position on entering the img, so 4 exapmle, if img has 100px with. if entering vom 0->50px left-> right, if 51-100, right->left or?

  7. To be able to detect left or right, I’d probably set up each element within the nav with an index and then shift left or right depending on whether the current index is higher or lower than the last index.

    David, thanks for porting the work over to Mootools. It looks good!

  8. @Mark: I think what I would do is the same as Alelo. Check where the mouse entered the image and move the background accordingly.

    @Jonathan Snook: Thanks!

  9. Strange, that was about to be my next blog entry :O

    I love doing this kind of thing. Flash certainly has it’s abilities that javascript can’t even touch, but most of the time javascript effects are every bit as good for buttons.

  10. Awesome! Thanks

  11. Great tutorial! Thanks. Added to tutlist.com

  12. Great tutorial! Thanks. Added to tutlist.com

  13. Very nice indeed – the effect’s not too in-your-face, nice and fairly subtle. I like it :)

  14. Jonathan

    Effect is not working on Mootools 1.2.1

  15. Jonathan

    Ok, thanks! I download again a mootools 1.2.1 and it works now.

  16. Hi David, thx too much, i used this script in new layout of my site.
    bye
    Nunzio

  17. visesh

    David,

    I am trying to change the bg color of visited links using this menu, any idea how to get that done.

    Thanks
    Visesh

  18. Hi David,
    i was looking another time this post, ‘because i like a lot it… i suggest you an idea… you can optimize the third animation using two senses of horizontal transition.. in this way if i arrive from the link to the left it seems that the blue band follow me, and the same if arrive to the link on center from the right link… like you in this moment

    what do you think about it? I’m interested on your opinion because I’m thinking if it’s better to use a DIV that follow my mouse movement (like an arrow that I’m developing for a web site in these days) or using this trick CSS/JS can be a good idea …

  19. wow…. this is awesome.. i like the second demo…

  20. Hi David,

    Is there anyway to keep the “hover” state active, until you click on one of the other links?

  21. Hello, on my site don’ t work with opera and firefox! but with ie and chrome work…

  22. Can you do it with mootools 1.1?

    I’ve been trying with fx.styles but I get an error with IE when I try to change “background-position”, other properties work fine!!!

    have you got any ideas?

  23. William

    Ya I’ve been trying to do it with mootools 1.1 too. Background-position gives an error that saids ‘push’ is null or not an object. Help~~

  24. William: 1.1 is almost 2 years old now — time to upgrade?

  25. William

    @David Walsh: I know :( However, my site runs on joomla and it’ll be a lot of backward coding if I upgrade. The 1.1 layer doesn’t work with half of my scripts running on the site now.

  26. Roark

    @William I have the same problem as you, Joomla bounds me to the confines of 1.11,
    I needed the same effect and used fx.styles. seemed to work ok in ie6:

    var gallery_a = $$('#slideshow ul li a');
    	gallery_a.each(function(element) {
    		var fx = new Fx.Styles(element, {duration: 300, wait: false, transition: Fx.Transitions.Sine.easeIn});
    		element.addEvent('mouseenter', function(){
    			fx.start({
    				'background-position': ['290px 0px', '253px 0px'],
    				'padding-right': ['0px','50px']
    			});
    		});
    		
    		element.addEvent('mouseleave', function(){
    			fx.start({
    				'background-position': ['253px 0px', '290px 0px'],
    				'padding-right': ['50px','0px']
    			});
    		});
    	});
    
    • Marek

      Hi Roark,

      thanks for this script you really saved my life :-). I had to changed it a little as I had to use horizontal background movement instead.
      Just in case if anyone will need it here it is:

      //

      Works fine in older MS IE !!!

      Great thanks again!!!

      br
      Marek

    • Marek

      Sorry the code:


      //

    • Marek
      window.addEvent('domready', function(){
      	var list_a = $$('#menu ul li a');
      	list_a.each(function(element) {
      		var fx = new Fx.Styles(element, {duration: 900, wait: false, transition: Fx.Transitions.Sine.easeIn});
      		element.addEvent('mouseenter', function(){
      			fx.start({
      				'background-position': ['-457px 1px', '0px 1px']
      			});
      		});
      		element.addEvent('mouseleave', function(){
      			fx.start({
      				'background-position': ['0px 1px', '-457px 1px']
      			});
      		});
      	});
      });
      
  27. Rasul

    Hi David;

    if one of “Li”s (first li, for exmple) has “current_page_item” class (class=”current_page_item”) like wordpress menu; how can I disable events for it?

    Thanks.

  28. lineblu

    Hi David,

    is there no solution for an active state of a navigation element.
    You have been asked twice (@visesh, @rasul) how to realize an exception for
    “visited links” or “current active links”, but you didn’t write any reply to these requests.

    I have the same problem and I hope you can find a little time to answer.

  29. lineblu

    The solution for the active menu element:

    if(!el.hasClass('current')) {
    	el.setStyle('background-position','-20px 35px').addEvents({
    		'mouseenter': function(e) {
    			e.stop();
          el.setStyle('color', '#FFD700');
    			fx.start('background-position','-20px 94px');
    		},
    		'mouseleave': function(e) {
    			e.stop();
    			fx.start('background-position','-20px 35px');
          el.setStyle('color', '#000000');
    		}
    	});
    }
    
  30. Suresh

    Very nice thanx

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

  • Prevent Chrome from Translating a Page

    A while back I shared my favorite Google Chrome extension:  Google Art Project.  I've enjoyed seeing beautiful art when I open a new tab -- it's brought genuine happiness to my day, however small that happiness may be.  About a week ago, however, the art presented had...

  • Create Any Type Of Website With These Multi-Purpose Themes

    We have selected what we believe are the very best multipurpose WordPress themes on the market today. Our list contains a number of best sellers, several newcomers that are proving to be highly popular, and a few themes that are ideal for creating the types of...

  • An Introduction to Static Site Generators

    Static site generators seem to have been becoming more and more popular recently, but they’re not one of those ephemeral novelty things that grow in popularity as quickly as they fall into oblivion shortly after. For over a decade, many different projects — 394 of...

  • Automated Tests for Visual Responsive Layouts

    Today it's all about testing. In 2015, many developers knows about TDD and I personally think that testing is one of the key for quality products. But what about testing in a Front-end environment? How do you guys write your tests for a responsive page or...

  • Getting Dicey With Flexbox

    What if you could build complex CSS layouts in minutes? Flexbox is a new CSS layout spec that makes it easy to construct dynamic layouts. With flexbox, vertical centering, same-height columns, reordering, and direction agnosticism are a piece of cake. There's a popular myth floating around that...