Beautiful Background Image Navigation with jQuery

In this tutorial we are going to create a beautiful navigation that has a background image slide effect. The main idea is to have three list items that contain the […]

In this tutorial we are going to create a beautiful navigation that has a background image slide effect. The main idea is to have three list items that contain the same background image but with a different position. The background image for each item will be animated to slide into place in different times, creating a really nice effect. The background image sliding direction from the list item in the middle will depend on which item the user was before: coming from the right, it will slide from the left and vice versa.

On top of that we will have sub-menus that appear with their semi-transparent background sliding in. These backgrounds create an awesome effect of actually just being one element that slides into place, changing its color.

Note: There is a new version which let’s you customize things better:
Sliding Background Image Menu with jQuery

We will be using the amazing Background-Position Animation Plugin by Alexander Farkas.

The photos that we will be using are from Pat’s beautiful B&W collection on Flickr.

There will be a little bit of CSS3 involved which absence will almost not be notable when using a browser that does not support its properties (like IE).

We tried to make this one cross-browser compatible and voilà! It works beautifully in Google Chrome, Firefox, Opera, Safari, IE8, IE7 and guess what, it even works respectively in IE6. (We are using an adapted style sheet and you will have to apply some PNG fix if you want the sub-menu backgrounds to be  semi-transparent. )

OK, so let’s get started!

The Markup

The HTML will consist of a wrapper div and an unordered list with three list items. We will initially set some “bg” classes that will have the respective background images. The “menuWrapper” will always have the “bg” class of the current list item so that we have the background image of the current list item.

<div id="menuWrapper" class="menuWrapper bg1">
	<ul class="menu" id="menu">
		<li class="bg1" style="background-position:0 0;">
			<a id="bg1" href="#">Our Passion</a>
			<ul class="sub1" style="background-position:0 0;">
				<li><a href="#">Submenu 1</a></li>
				<li><a href="#">Submenu 2</a></li>
				<li><a href="#">Submenu 3</a></li>
			</ul>
		</li>
		<li class="bg1" style="background-position:-266px 0px;">
			<a id="bg2" href="#">Our Brands</a>
			<ul class="sub2" style="background-position:-266px 0;">
				<li><a href="#">Submenu 1</a></li>
				<li><a href="#">Submenu 2</a></li>
				<li><a href="#">Submenu 3</a></li>
			</ul>
		</li>
		<li class="last bg1" style="background-position:-532px 0px;">
			<a id="bg3" href="#">Contact</a>
			<ul class="sub3" style="background-position:-266px 0;">
				<li><a href="#">Submenu 1</a></li>
				<li><a href="#">Submenu 2</a></li>
				<li><a href="#">Submenu 3</a></li>
			</ul>
		</li>
	</ul>
</div>

For the background animation plugin to work correctly we need to set the position of the background image as inline styles initially. We already set the right position for each background image, for example, the third item will have the background image positioned to the outer right.

As you can see, every list item has another sub-list with three more items. The background image position of these sublists is set to a value that hides the image. When we animate the background then, we will create the effect of sliding it in from the left or the right.

The CSS

Let’s start by the general style of the the “menuWrapper” which will contain the font styles and the size of the whole element:

.menuWrapper{
    font-family: "Trebuchet MS", Arial, sans-serif;;
    font-size: 15px;
    font-style: normal;
    font-weight: normal;
    text-transform:uppercase;
    letter-spacing: normal;
    line-height: 1.45em;
    position:relative;
    margin:20px auto;
    height:542px;
    width:797px;
    background-position:0 0;
    background-repeat:no-repeat;
    background-color:transparent;
}

The list and the list items of the first layer will have the following style:

ul.menu{
    list-style:none;
    width:797px;
}
ul.menu > li{
    float:left;
    width:265px;
    height:542px;
    border-right:1px solid #777;
    background-repeat:no-repeat;
    background-color:transparent;
}
ul.menu > li.last{
    border:none;
}

The selector “>” addresses only the li elements of the first layer and will not be applied to the ones of the sub-menus. We will give the last li the class “last” in order to remove the right border.

The following three classes define the background images. We will give these classes to all the li elements depending on which one we hover. So, if we hover the second li, we will give the “bg2” class to all the first layer list items:

.bg1{
    background-image: url(../images/1.jpg);
}
.bg2{
    background-image: url(../images/2.jpg);
}
.bg3{
    background-image: url(../images/3.jpg);
}

Let’s define the look of the link elements in the first layer list. Since the li elements have a big height, we need to push the link elements down. We do that by setting a high top margin:

ul.menu > li > a{
    float:left;
    width:265px;
    height:50px;
    margin-top:450px;
    text-align:center;
    line-height:50px;
    color:#ddd;
    background-color:#333;
    letter-spacing:1px;
    cursor:pointer;
    text-decoration:none;
    text-shadow:0px 0px 1px #fff;
}

To center the text of a link element vertically, you can give a line-height value equal to the height of the element. (I don’t know why, but when I started with learning CSS, I automatically always used paddings to adapt the height of the element and to center it. Using line-height was a real delight because you can control sizes much better like that.)

The second layer lists would naturally appear after the first layer list, so we use a negative top margin to “pull” them up:

ul.menu > li ul{
    list-style:none;
    float:left;
    margin-top:-180px;
    width:100%;
    height:110px;
    padding-top:20px;
    background-repeat:no-repeat;
    background-color:transparent;
}

The li elements of the sub-menu will be initially hidden. In the script we will fade them in when we hover over their parent list item link:

ul.menu > li ul li{
    display:none;
}

Now we define the classes for the background images of the sub-menus:

ul.menu > li ul.sub1{
    background-image:url(../images/bg1sub.png);
}
ul.menu > li ul.sub2{
    background-image:url(../images/bg2sub.png);
}
ul.menu > li ul.sub3{
    background-image:url(../images/bg3sub.png);
}

The link elements of the li elements will have the following style:

ul.menu > li ul li a{
    color:#fff;
    text-decoration:none;
    line-height:30px;
    margin-left:20px;
    text-shadow:1px 1px 1px #444;
    font-size:11px;
}

ul.menu > li ul li a:hover{
    border-bottom:1px dotted #fff;
}

The first sub-list will be shown in the beginning:

ul.menu > li ul.sub1 li{
    display:block;
}

And that’s all the style. Take a look at the ZIP file for the IE6 style sheet.
Now let’s take a look at the JavaScript.

The JavaScript

What we do in the script is the following: we first check where we are coming from and then we animate the background positions of the list elements in the first level and the backgrounds of the sub-menus accordingly:

$(function() {
	/* position of the <li> that is currently shown */
	var current = 0;

	$('#bg1,#bg2,#bg3').mouseover(function(e){

		var $this = $(this);
		/* if we hover the current one, then don't do anything */
		if($this.parent().index() == current)
			return;

		/* item is bg1 or bg2 or bg3, depending where we are hovering */
		var item = e.target.id;

		/*
		this is the sub menu overlay. Let's hide the current one
		if we hover the first <li> or if we come from the last one,
		then the overlay should move left -> right,
		otherwise right->left
		 */
		if(item == 'bg1' || current == 2)
			$('#menu .sub'+parseInt(current+1))
			    .stop()
				.animate({backgroundPosition:"(-266px 0)"},300,function(){
					$(this).find('li').hide();
				});
		else
			$('#menu .sub'+parseInt(current+1))
				.stop()
				.animate({backgroundPosition:"(266px 0)"},300,function(){
					$(this).find('li').hide();
				});

		if(item == 'bg1' || current == 2){
			/*
			if we hover the first <li> or if we come from
			the last one, then the images should move left -> right
			*/
			$('#menu > li')
				.animate({backgroundPosition:"(-800px 0)"},0)
				.removeClass('bg1 bg2 bg3')
				.addClass(item);
			move(1,item);
		}
		else{
			/*
			if we hover the first <li> or if we come
			from the last one, then the images should move
			right -> left
			*/
			$('#menu > li')
				.animate({backgroundPosition:"(800px 0)"},0)
				.removeClass('bg1 bg2 bg3')
				.addClass(item);
			move(0,item);
		}

		/*
		We want that if we go from the first one to the last one
		(without hovering the middle one), or from the last one
		to the first one, the middle menu's overlay should also
		slide, either from left to right or right to left.
		 */
		if(current == 2 && item == 'bg1'){
			$('#menu .sub'+parseInt(current))
			.stop()
			.animate({backgroundPosition:"(-266px 0)"},300);
		}
		if(current == 0 && item == 'bg3'){
			$('#menu .sub'+parseInt(current+2))
			.stop()
			.animate({backgroundPosition:"(266px 0)"},300);
		}

		/* change the current element */
		current = $this.parent().index();

		/* let's make the overlay of the current one appear */

		$('#menu .sub'+parseInt(current+1))
			.stop().animate({backgroundPosition:"(0 0)"},300,function(){
				$(this).find('li').fadeIn();
			});
	});
	/*
	dir:1 - move left->right
	dir:0 - move right->left
	 */
	function move(dir,item){
		if(dir){
			$('#bg1').parent()
					 .stop()
					 .animate({backgroundPosition:"(0 0)"},200);
			$('#bg2').parent()
					 .stop()
					 .animate({backgroundPosition:"(-266px 0)"},300);
			$('#bg3').parent()
					 .stop()
					 .animate({backgroundPosition:"(-532px 0)"},400,function(){
						$('#menuWrapper').removeClass('bg1 bg2 bg3')
										 .addClass(item);
					 });
		}
		else{
			$('#bg1').parent()
					 .stop()
					 .animate({backgroundPosition:"(0 0)"},400,function(){
						$('#menuWrapper').removeClass('bg1 bg2 bg3')
										 .addClass(item);
					 });
			$('#bg2').parent()
					 .stop()
					 .animate({backgroundPosition:"(-266px 0)"},300);
			$('#bg3').parent()
					 .stop()
					 .animate({backgroundPosition:"(-532px 0)"},200);
		}
	}
});

And that’s it! A beautiful cross-browser capable effect!
I hope that you enjoyed the tutorial.

Message from TestkingIf want to learn professional web designing but have no time to attent regular class then testking a+ is best solution though. Download the testking mcse design tutorials and testking VCP-410 study guide to learn how to create beautiful and unique logo designs.

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 335

Comments are closed.
  1. I LOVE this menu! does anyone have any idea how to integrate it into joomla?

  2. I am wondering if it is possible to use jquery to bring up the menu selected page as another layer semi transparent overlaying the entire menu, with a ‘close’ option for navigation? Being a complete noob with this my current attempt simply opens new pages of content, and that distracts for the beauty of this design completely.

  3. i would like to know how i can include a new block , so the navi has 4 columns

    thanks for helping code will be appreciate

  4. I have this running in Joomla!

    Still have a few issues to resolve and will then post my results soon!

  5. I have amended the code as follows to make invisible regions with content appear when the sub menus are selected. At the moment these ‘regions’ are just divs with basic content in them whilst I try and figure out how it all works.

    My problem seems to be the handling of multiple regions or divs, one for each of the menu selections.

    I firstly define the style:
    #layer1 {
    position:absolute;
    top:10px;
    left:200px;
    z-index:0;
    visibility:hidden;
    }
    #layer2 {
    position:absolute;
    top:10px;
    left:200px;
    z-index:1;
    visibility:hidden;
    }

    Then I add the javascript:
    function Toggle(‘layer1’) {
    var elm=document.getElementById(‘layer1′);
    elm.style.visibility=(elm.style.visibility==’hidden’)? “visible” : “hidden”;
    }
    function Toggle(‘layer2’) {
    var elm=document.getElementById(‘layer2′);
    elm.style.visibility=(elm.style.visibility==’hidden’)? “visible” : “hidden”;
    }

    Then the hidden DIVs:

    THIS IS LAYER 1POSITIONED AT 100,100

    THIS IS LAYER 2POSITIONED AT 100,100

    And finally I add the action to the existing page as you have it here:
    understanding hotspots

    buying hotspots

    Sadly nothing works. If I make this a simple toggle action between two divs then it works, because I can simplify it, but I want to list up to 9 hidden divs to display depending on the sub menu selection made. Mary Lou, or anyone, can you spot where I have coded this wrongly? Please ignore the positioning and the div’s styling at the moment, they are just done this way for the testing.

  6. Oops, my code examples do not show up correctly – grrrr – not sure how to fix that. Sorry Mary-Lou! Can you still figure out what I’m trying to achieve?

  7. I just wanted to thank you so much for providing this brilliant (one amongst many) tutorial – my website is effectively a homage to my appreciation of you!

  8. It’s a beautifull effects,but please can anyone help me?
    Try to change the size of the background image (mine are 640×428) but it don’t work well,why?
    I don’t have other js in lace but the container breakdown

  9. To R.Bird and/or Mary Lou: I downloaded your modified menu containing 4 panels. I tried to follow the logic and add a 5th panel but it ultimately failed. The 5th panel appeared but I could never adjust the background position of the images so they lined up properly (they become more askew as you got closer to the 5th panel) and when I hovered over the 5th panel main menu item, all the background images disappeared but you could see the sub menu items (no background image on the sub menu items either).

    If there is anyway to explain how to successfully add additional panels on to your modification, I would greatly appreciate it. Another person posted he had added 4 additional, a total of 8 so I know it can be done.

  10. Hi Max, I’m the guy that did the eight slicer, thanks to Bird’s script tweak he published earlier in here. I have uploaded my sketchy work so you can do a page “view source” and see for yourself how the code is built. Basically, you have to figure out the total width of your image and divide it by the number of slices you want. Lets say a 1000px wide image divided by 5 slices = 200px from there you will see that you have to use 200, 400, 600, 800 increments in your coding substracting or adding 200px forward and backward…and so on = it’s all maths. The result of my exercice is not a perfect one; there is something in the script that still needs further tweaking for cleaning up animation. But if you mouse away instead of surfing through from one of my slices to come back to a slice with the mouse out, everything works forward or backward. Anyways, wait a little for page to load fully before mousing around = it’s just an experiment I did.
    Here’s the LINK!

  11. Hey! Please advise, how do I hide menu when it’s not mouseovered?

    I want submenu to appear only when user mouse over it.

    Thanks.

  12. this is very nice work. wonderful!
    but i have a question. in here we can put only,
    Submenu 1
    Submenu 2
    Submenu 3 etc….

    but if want to introduce
    Submenu 1
    Submenu 1.1
    Submenu 1.2
    Submenu 1.3

    Submenu 2
    Submenu 2.1
    Submenu 2.2 etc…

    in here introduce like this menu is very difficult.
    if we can integrate like this menu
    http://tympanus.net/codrops/wp-content/uploads/2009/09/css3_dropdown/
    to the upward, this will be the best jQuery in the world.
    but is it possible ????

  13. Very nice demo – could definitely see this replacing Flash at some point. I have an issue with it in that it DOES NOT degrade nicely. IN a non-javascript browser (or with Javascript turned off) you lose access to most of the features. Can you address this please? Maybe a revised example? Or a fresh blog post?

  14. Hello! I cant add submenus in correct position. When i add subs, it stay down. Anyone can hep me?

  15. How do I hide menu when it’s not mouseovered. submenu should appear only when user mouse over it.

  16. Mary Lou, this is an awesome, beautiful nav menu; i’ll be tweeting it from imdesigntank.

  17. Hi,

    All the works on your site i looked is awesome. Great works and dedication.

    thanks

  18. Hi, This is lovely, i’m currently rebuilding my site and intend to use the 4 panel version of your script, hope that’s ok, but I wondered if there was an easy way for the panels to change with a javascript delay, incase the user doesn’t hover over the menu? Thanks again.

  19. Hi Mary,

    first of all what a fantastic thing this is. I have just started to re-design my website and absolutly have to have this on it as it fits perfectly with the design I had in mind.

    I tried playing around with the file i downloaded before personalising it and it was working fine.

    As soon as i moved the code into my own html file it didnt work. Only shows up the one picture.

    So i scrapped everything and went through your tutorial step by step but still didnt work.

    I would be very grateful if you can help me fix this problem. I have uploaded the page to a subdomain please can you take a look for me?

    Many many thanks in advance

    http://newsite.rdosolutions.com/services.html

  20. Hi its me again…

    Well I figured it out at last… Amazing… It is fantastic… I just need to find out how I can preload the images to make it faster, I also need to play around a bit with positioning and the image on the left seems wrong so need to look into why its like that, so if anyone can help with that I will be very happy…

    Once ive done that all I will start to work on the images themselves as they are just temporary…

    Thank you so much for this amazing thing you have supplied to the world…

    http://newsite.rdosolutions.com/services.html

  21. Maybe it is because I haven’t ad much sleep over the last few days, but for the life of me I cant figure out how to raise the whole thing up to my nav bar and also to get rid of that unsightly thing n the far left image… arrhhgg… I need it to match the home page exactly… please can someone help me??

  22. I have modified this script considerably to dynamically work as a module within the Joomla CMS. However, I would like to have the sub menus hidden, and only appear on mouseover of the parent menu items. No matter what I try in the code I cannot hide the submenu. Can anyone help? The url is:

    http://www.beta.tenens.com

    Thanks

    Lee Tempest

  23. Hello Mary Lou, i am having problems with the image navigation when I upload my page to the server, but form my computer it works perfectly, any suggestion??? thanks i would really appreciate your help

    http://cervecitadulce.com/

    🙂

  24. INEDESK,
    I think your problem is a javascript conflict, you have lots of javascript loading, also the javascript should go in the of your site. I would suggest removing all other javascript calls except for the one to run this menu. The javascript you have at the bottom of your code needs to be before the menu code. Hope that helps!

    Lee

  25. AWESOME!
    I like some I saw would like to know if anyone can:
    1. Have only the nav bar visable until mouseover.
    2. Support 2nd level submenus
    3. Change the position of the nav bar displayed from the top down, instead of bottom up.

    I’ve seen some really great examples out there. I my world of regular commercial work, it would be much more pratical for it to impress, but then disappear while presenting the main page content.

    Any ideas?

    btw, Mary, I am truely impressed with your creation and knowlege.

  26. Thanks I already solved it , im not sure what I did but it works now , thank very much : ) Lee tempest

  27. Thank You Very much,
    I Have a Problem , How can i add more slides, eg. I want 4 slides,
    I would be very please if you can help me on this

  28. Can anyone tell me how I might get this to “auto-play”? I’d love to make the flip occur every 5 seconds or so.

    Thank you very much, in advance! This is a fantastic effect.

  29. My bad! I just renamed my images to your naming conventions – voila!
    Really, really, fantastically beautiful Mary Lou!

  30. I have the same issue as Alex in that i have setup a five panel version, but panel 4 goes the wrong way but is fine the other way, i’ve spent around 5 hours pulling it all apart and putting back together but i cannot figure out why.
    Any help would be great.