Garage Door Style Menu (using Animated Background Images with jQuery)

* 7/21/2008  —  68 Comments *

by: Chris Coyier

Right out of the box, jQuery provides the animate function, which allows us to morph some CSS attributes over time. Things like opacity, font-size, width, length, and position are all supported. There are a couple of notable limitations to this function though, and one of those is “background-position”.

Thankfully, there is a plugin to help with this, the Background-Position Animation Plugin by Alexander Farkas. (direct link to JS). With this, we can do some fun stuff!

We are going to build a “Garage Door” style menu, where an image “slides up” to reveal another image behind it.

View Demo Download Files

1. Creating the image needed

We are going to need three different types of images here. First is a background image for the entire menu itself. This is going to be one big image for the entire menu which will be the imagery which is “revealed” when the door opens. Check out my Photoshop file:

Notice my guides. I have these set up as a visual reference to what the “viewable area” is going to be within the garage frame. Note that the Photoshop files are included in the download for your reference.

Second, we’ll need to create the garage doors which we will call the “shutters”. These need to be separate graphics as each one will need to be animated separately. I made a separate template for this, so I could again use guides to keep things as close to centered and nicely spaced as possible.

Lastly, we need a window which will act as the garage frame. This is the nice touch that really ties the whole idea together. Since this is going to be the top-most layer, we will apply this to the anchor links themselves, so that they can be clickable with unique URLs.

2. Writing the HTML markup

Of coure, no matter how fancy we want to get with our menus, the markup should be clean and semantic so that with CSS and/or JavaScript disabled, the menu still looks and behaves like a menu.

Here is the menu markup:

<ul id="menuback">
	<li class="shutter" id="shutter1"><a class="link" href="#1">Link 1</a></li>
	<li class="shutter" id="shutter2"><a class="link" href="#2">Link 2</a></li>
	<li class="shutter" id="shutter3"><a class="link" href="#3">Link 3</a></li>
	<li class="shutter" id="shutter4"><a class="link" href="#4">Link 4</a></li>
</ul>

We have classes and ID’s applied all over, as we will need those hooks to do the styling and behaviors we want. But with CSS turned off, we have a very functional menu still:

3. The CSS

Here I’ll show you the whole CSS file, and then point out a few things below:

* 				{ margin:0px; padding:0px; }
body				{ background:#c1c1c1; }
a 				{ outline-style: none; }

ul#menuback {
	margin: 50px auto;
	list-style: none;
	background: url(../images/menu-bg.jpg);
	width: 800px;
	overflow: auto;
}

ul#menuback li.shutter {
	width: 200px;
	height: 100px;
	display: block;
	float: left;
}

ul#menuback li#shutter1 {
	background: url(../images/shutter-africanplains.jpg) no-repeat;
}
ul#menuback li#shutter2 {
	background: url(../images/shutter-reptiles.jpg) no-repeat;
}
ul#menuback li#shutter3 {
	background: url(../images/shutter-aviary.jpg) no-repeat;
}
ul#menuback li#shutter4 {
	background: url(../images/shutter-arcticzone.jpg) no-repeat;
}

a.link {
   width: 200px;
   height: 100px;
   display: block;
   background: url(../images/window.png) no-repeat bottom center;
   text-indent: -9999px;
}

We use the hard star-selector reset for cross-browser consistency. This is especially important in this example as differences in the margin and padding values for lists are common across different browsers.

The menu background is applied to the UL itself. Then each list item is set to a specific width and height (that of our window) and floated to the left (for a horizontal menu). The ID values on the LI items are used to apply the separate background graphics only. The anchor links, as I mentioned above, will be the top-most layer and thus use the window overlay. These will need to be set as a block level element, have with and height applied, and use text-indent to kick the text off the page.

4. The jQuery JavaScript

First things first, we include the latest version of jQuery on our page, as well as the plugin I linked to at the top of this article. Then we can write the jQuery JavaScript needed to make the garage door effect happen.

<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="js/jquery.backgroundPosition.js"></script>

<script type="text/javascript">
	$(document).ready(function() {

		//Set css in Firefox (Required to use the backgroundPosition js)
		$('#shutter1').css({backgroundPosition: '0px 0px'});

		//Animate the shutter
		$(".link").hover(function(){
		      $(this).parent().animate({backgroundPosition: '(0px -100px)'}, 500 );
		    }, function() {
		      $(this).parent().animate({backgroundPosition: '(0px 0px)'}, 500 );
		});
	 });
</script>

The first statement above is to account for a Firefox quirk actually. Just need to reset that background-position to 0px 0px.

Then we bind the “hover” event to each page element with the class of “link”. Remember we applied that class to each anchor link in the markup. We could have just used “a” as the target here, but that is dangerous as it is likely there will be more anchor links on any page this is actually used, so better to target a specific class. So when the hover event occurs over a page element with a class of “link”, jQuery finds the parent element, and does the background-position animation on that element. In our case, the LI element, with the unique shutters. Using the call-back function of the hover event (e.g. when the mouse leaves the area) we can animate the shutter back into position.

And there we have it, a nice looking menu with a pretty neat animated effect!

View Demo Download Files

 

Special Thanks

Special thanks to Toby Pitman for the orginal concept for this idea. Toby helped out another reader having a problem with background image animation on this thread. The basis for this example is from the example he posted there.

Responses

  1. Shannon Snow says:

    This is very cool, I will definitely need to keep this and use it somewhere!

  2. Oops! On IE7 only works the first door!

  3. mal says:

    Really nice effect, but Josep Viciana is right in IE only the first door works.

  4. Faris Raouf says:

    Yup, extremely cool, but as others have said IE7 barfs on anything other than the first door.

    Line 23, char 16, ‘undefined’ is null or not an object (happens when you hover over the second or subsequent doors)

    It is obviously scared of the snake :-)

  5. Remkus says:

    Extremely cool effect, but like Josep says it has flaw.. it also only shows ‘what’s behind door # 1′ in FF2

  6. Only opens the first door in FF2 and MSIE7 on XP Pro SP3.

  7. dangdang says:

    Funny behavior in FF3. The “Link1″ “Link2″ etc. text links still show up and the doors only open when you hover over the text links not the entire block?

  8. Chris Coyier says:

    This problem in IE 7 and FF2 should be fixed.

  9. dangdang says:

    Yep! Works great now on XP-SP3 FF3! This is awesome! I will be using it soon. Thanks!

  10. Karl says:

    Hey Chris, did you get dugg (digg’d)? Been over half an hour trying to read this article. Glad I finally made it.

  11. htl says:

    I move my mouse over and out of the pictures 5 times, and they still animates although i’ve move my mouse out :D

  12. anonymous says:

    yeah, there seems to be a bug .. you didn’t ignore the mouse event if you are already in the process of opening/closing the garage door.

    Just move your mouse over the door 10 times very quickly and then move it out….

  13. Gordon says:

    Can’t see what all the fuss is about. It is a great bit of coding, and it works absolutely fine in Firefox 3.0.1, Opera 9.27, Safari for Windows 3.1.2 (525.21). Maxthon 2.1, and IE7 7.6.6006.18000 all on Windows Vista.

  14. yuki says:

    this was a css ah-ha moment, thanks.

  15. Grafiko says:

    cool technique, working fine in mozilla

  16. thomas peklak says:

    Cool stuff!!!
    Small enhancement: you could stop the animation when the mouse leaves, if it is still active.

  17. Phe Le says:

    You are one of my favorite!

    This is the coolest menu I’ve ever seen in my short life. I have been looking for a menu in which the hover image moves with the mouse when navigate through the menu. Have you seen that one?

  18. Chris, I would suggest putting .stop() in there like:

    $(this).parent().stop().animate(

  19. Chris Coyier says:

    @Benjamin: Ah ha, very nice. The live example has been updated and it works much nicer now. Helpful suggestions are always nicer than cries of “it’s broken!” =)

  20. Jarod says:

    What an awesome tutorial. This is my first time responding to a tutorial. I was impressed. Then again, I’ve been really impressed with jquery lately. Great tutorial. I’ve subscribed.

    Thanks,

    Jarod

  21. Mike says:

    Nice Job Chris!!

    You finally got me to say: nice, I have been waiting for one of yours to impress! Great work, nice effect, well planned, well documented, from one designer/developer to another.. pat yourself on the back.. best one yet! Keep them coming, I only hope to follow your lead and actually start using my blog.

    Nice comments box too! Glad I finally used it!

  22. Really nice effect! I love JQuery, so simple to get something which looks as good as something done in flash

  23. ty says:

    I really love the menu.
    In my debugging install of IE6 all that is seen is light blue background color rounded corner boxes (perhaps because they are png images). And on mouseover a quick flash of the background, probably a hover glitch?
    Great technique, and as a plugin with the bugs worked out would be just killer.

  24. Joe McCann says:

    Sick and slick. Nice work once again.

  25. Chris, If you can working in the bounce effect, that would really make it pop.

  26. David Walsh says:

    I hate to quote you here, but….didn’t I request an ass shot?

  27. great stuff!!, cross browser also :D

  28. Very ingenious. Would you create vertical one?

  29. Graeme says:

    Thanks for this Chris, it will be incorporated into my blog re-design as a way to show off my latest work.

    Thanks again!

  30. Harry Mannemela says:

    Hi,

    I have downloaded the files and when I opened the page, I am not getting any slides or so in IE6 (XP).

    It works fine in Mozilla thou.
    Could someone help me to tweak it so that it works in IE6 and IE7?

    Thanks in advance,
    Harry

  31. Alper says:

    hey but it’s not work on IE6??

  32. elvisparsley says:

    This is great, but what a shame that it does not work in ** IE6.
    Can anyone work it out please?

  33. Vitaliy says:

    And where script updates for IE6????

  34. Luc says:

    Anyone found a solution for the error with IE?

    Line 23 char 16 – Undefined bla bla bla….

    because i need 8 boxes… any help would be much appreciated

    All other browsers work well…. but not IE… please help help help….

  35. I really think that IE6 is now rather outdated, and visitors to this page who complain that the routine does not work should really update to the latest version of IE from the Microsoft web site.

    It would then save lots of moans and groans.

    Personally I have found that the routine works in ALL of the most used current version browsers.

  36. Luc says:

    Gordon Tatler – not sure if you are referring to my post but i’m talking about IE7

    Are you able to have 8 boxes and they all work well?

    4 I’m ok…. 8, not…. any idea or solution to suggest?

  37. elvisparsley says:

    Gordon, I assume you are not a web developer. Unfortunately there are many people out there who are using IE6. When we make a website, we have to accomodate them as well. So you are completely missing the point.

  38. ElvisParsley: No, I am not a web developer, and as such may not be fully aware of all the niceties of web development and backward compatibility.

    However, until recent retirement I was a network administrator with over 100 computers under my control. Whenever new operating systems, applications or browsers were released I always thoroughly tested them and then, provided they passed my testing and were necessary to the function of the network, I would fully deploy them. So, all of my computers were kept up to date with the latest technology.

    I believe that the Microsoft update page should now automatically update IE to version 7 – most probably version 8 later this year, so the question I ask is why there should be so many “out there” still using IE6 ? Are they not updating their computers regularly (they really should be doing so) ? Or is this a perceived problem only – I ask as my own web statistics seem to indicate the rapid downturn in IE6 visitors to an almost negligible number, IE7, Firefox and Opera taking the top 3 positions.

    So the question I am interested in is :- how far should backward compatibility be taken ? Why stop at IE6 ? How about IE 5.5, IE5, IE4 …….. ? There has to be a stopping point somewhere. Even Microsoft eventually give up !

    Comments ?

    Oh, and by the way. Anyone tried out the new Google Chrome browser yet ? It’s available at http://www.google.com/chrome/ and this menu also works in that.

  39. Robert says:

    Anyone know what I need to change on this to make it run as a php file? In other words, if I rename the .html file to .php what do I need to change for it to work? Because that change has broken mine :)

  40. sanimoyo says:

    To fix the only one window openning problem,on the jquery that you copy from this site, after the;

    $(’#shutter1′).css({backgroundPosition: ‘0px 0px’});

    add

    $(’#shutter2′).css({backgroundPosition: ‘0px 0px’});
    $(’#shutter3′).css({backgroundPosition: ‘0px 0px’}); $(’#shutter4′).css({backgroundPosition: ‘0px 0px’});

    All your windows will open, I hope that helps, great menu by the way.

  41. buckmajor says:

    Hey everyone

    Im newbie here, just wanted to say how impress I am with this website and the techniques used in css which amazes me the most.

    Awesome stuff man, hope to reach that kind of level one day lol.

    CHEERS :)

  42. sfdude says:

    Chris,

    DEMO works great under FF3,
    but not at all in IE6 (under XP sp2).
    It just shows 4 empty boxes.

    Developers know better and use IE7, but
    many thousands of users still use IE6…

    Any way a fix can be found for IE6?
    HELP! Anybody take up the challenge?

  43. I noticed that if you downloaded the files from the top of the page instead of at the bottom that the fixes discussed in the comments are not fixed. Namely the “only the first tab works in IE”.

    To fix this change:

    $('#shutter1')

    to

    $('.shutter')

    This way the style is applied to all the shutters by class instead of a single shutter by id.

    The other problem of not seeing the shutters or BG image in IE6 is a PNG transparency issue. I found that this little bugger did the trick for me:
    http://jquery.andreaseberhard.de/pngFix/

    Hope that helps some people utilize this great example. Thanks a lot for the tutorial. I may be using this on Edinboro’s Site:
    http://www.edinboro.edu/test/testnav/testnav.dot

  44. It seems the text-indent used to hide the link text breaks the link from working in IE6. I am trying to figure out a way to fix this. My initial thought was to replace the text with a transparent gif, but I really like how the menu degrades so that if someone is using a screen reader they still just see it as a list. I suppose I could use alt text on the transparent gif, but not as nice.

    Anyone found a fix for this, that’s a little better than that?

  45. abhishek bhatia says:

    hi! I loved your menu. I would want to include a function that is triggered on an onclick event, such that the garage door for the link that I clicked on remains open and rest all remain closed. When you click on any other door, that will remain open leading to closure of the first door. That would be pretty cool. Can you suggest how could I achieve that?? or can you incorporate the changes.

  46. This is a brilliant effect. I will need to use this in future. Thank you

  47. Jake says:

    Hi Chris,
    1st wanted to say how much inspiration I get from your site!!!
    I did want to let others know (as to save a couple hours time) that the link to the jquery.backgroundPosition.js (at top) is a bit dated. It should be known that by using the code from that link will cause animation problems (could be my styling though). Best option is to go to "demo" and use "firebug" to view and copy code from jquery.backgroundPosition.js.
    Again Chris, much respect!

  48. Nicola says:

    Hi, I try the script into a tag div but doesn’ t work if div is avowed in the css script without any attribute. This problem is verify with FireFox 1.9.0.3257 while with IE 7 works without any problem.
    Background image results translante for any pixel on the left board.
    Any suggestion?
    Thanks
    Nicola

  49. Noel says:

    Hi Chris,

    Amazing effect. Well done.

    I am new to CSS and jQuery and I have it working on IE, Safari & Chrome. Looks OK in FF aswell until I click on a link and then the background image re-appears. Any ideas what I am doing wrong?

    Can be seen at http://www.thedanesbakery.ie/wip/index2.htm