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. Well its really a beautiful widget, i would like to use it somewhere in my blog, as its really beautiful.
    thanks for sharing.

  2. hi there
    Is there anyway all the submenus can be hidden rather than having the first visible by default, ie only show when you hover?

  3. hello again

    I added this @ the bottom of the script >

    {
    $(“li.bg1, li.bg2, li.bg3”).hover(function() {
    $(this).find(“span”).show();
    } , function() {
    $(this).find(“span”).hide(); //Hide the subnav
    });

    HTML >

    Submenu 1
    Submenu 2

    Submenu 3

    Not pretty but did work…

    Great script BTW

  4. I wanted to hide the sub menus as well until mouseover, but the coding mentioned in OMAN877 seems to have a script error? Are you adding this script to your current page after the move function?

  5. Really really nice menu, love the animation and used it for one of my portfolio pages.

  6. Thanks for this awesome solution.
    I found a issue when I zoom out the browser, the last image gets displaced…

  7. Hi all – this is an amazing widget and i would really like to use it at some point.

    However, i was having a little play around with it and for the life of me I can get fancybox or any lightbox type this to work with it. I’m not the most advanced javascripter but I’ve looked everywhere for an answer and can’t find one – i tried the noConflict thing but couldn’t get it to work.

    This is the javascript I want to put in the head section of my page…

    $(“#various3”).fancybox({
    ‘width’ : 300,
    ‘height’ : 70,
    ‘autoScale’ : false,
    ‘transitionIn’ : ‘none’,
    ‘transitionOut’ : ‘none’,
    ‘type’ : ‘iframe’
    });

    $(“#various4”).fancybox({
    ‘width’ : ‘75%’,
    ‘height’ : ‘75%’,
    ‘autoScale’ : false,
    ‘transitionIn’ : ‘none’,
    ‘transitionOut’ : ‘none’,
    ‘type’ : ‘iframe’
    });

    $(“#variousdelicious”).fancybox({
    ‘width’ : ‘75%’,
    ‘height’ : ‘75%’,
    ‘autoScale’ : false,
    ‘transitionIn’ : ‘none’,
    ‘transitionOut’ : ‘none’,
    ‘type’ : ‘iframe’
    });

    $(“#various5”).fancybox({
    ‘width’ : 300,
    ‘height’ : 70,
    ‘autoScale’ : false,
    ‘transitionIn’ : ‘none’,
    ‘transitionOut’ : ‘none’,
    ‘type’ : ‘iframe’
    });
    });

    any help would be awesome!

    Cheers

  8. Hello Mary Lou and Thanks to your “Jquery”.
    I would use your jQuery Menu with 5 menus (and no 3) and i have a problem with the javascript. My picture is not good cut.
    Can you help me.

    Ps : Sorry for my poor english traduction 🙂

  9. ok sorry, i’ve just seen the post of “R.BIRD” , this is the solution of my problem. Thanks

  10. i am trying to make the sublinks work also. i want them to be dynamic links that overlay the images with some text. any ideas?!?

  11. Mary Lou, I really like this tutorial. I am trying to figure out how make it fill the entire browser instead of having the background. Please help me. Thank you.

  12. I mean having the navigation and the pictures fill the entire screen instead of having the yellow background.

  13. Hi Mary Lou

    I love this tutorial and the effect to make a website attractive.

    For some reason I cant get mine to work. I looked at the source code and made sure that it is identical but I cant seem to get to work.

    Do you mind having a look at where i’m going wrong?

    http://www.billyyhman.site50.net/background.htm

    Thanks Billy

  14. Hi Mary Lou, Excellent work!!

    I was wondering if you can help me. I wanted to do 9 menus in three rows (3×3)
    But when I do it, the animation occurs only in the uper row.
    only when the animation ends the rest of the image appears…

    Thank you very much

  15. @Billy,
    the font is called “Brian Scratch” and you can find it here:
    http://www.dafont.com/brian-scratch.d2224

    Regarding your problem, I guess it’s because you are giving different names to the images but the script expects them to be numbered, i.e. 1.jpg
    You can change that in the script or you can simply rename your images. Hope it helps,
    ML

  16. Nice!
    There´s some detail…

    .menuWrapper{
    font-family: “Trebuchet MS”, Arial, sans-serif;;

    Double semi colon, but this is the best that i saw from jquery, talking about menu style.

  17. Can anybody tell me if this script will work with other jquery tools? I have been toying with this for a couple of weeks now and I can’t seem to get it to play nice with any other jquery plugins.

    any insight would be greatly appretiated.

    many thanks in advance.

  18. beautiful work!
    just two questions pls?
    how to change color, padding and other stuff on Menu?
    when you zoom out, the third menu comes down below the other two… why is that?

  19. and one more thing pls
    how to put a page instead of background.. so the page could have that effect?

  20. beautiful tutorial… bravo
    how to make no submenus to appear when the page opens?
    i want them to appear only on mouseover?
    thank you

  21. This is delicious; having some trouble integrating into WP3 w/ what seems to be an included jquery 1.4.2 which does not work for this menu.

  22. Dear Mary,

    I have sent you a massage about a possible project via your contact form some days ago and I didn’t receive any answer from you.

    Did you get it?
    How can I contact you?

    Thanks a lot
    D.

  23. Hi MaryLou and to all,
    simply smart navigation !
    I try to integrate on submenu “lightbox 2.0” but is it in conflict with “//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js” and “lightbox 2.0” not work, any other experienced “script for overlay images” ?
    Have a new great year.

  24. Hi to all,
    feedback for my above post,
    try and try…after work
    is a order list and a modification of “$(function()” from a code in link posted on this forum in the past months:
    —————————————————-
    in

    in

    $.noConflict();
    jQuery(document).ready(function($) {

    /* $(function() { */
    —————————————————-
    Hope is all intended for help.
    Best regards people !

  25. my post is truncated on publishing ,
    may i edit it for clarification ?

    Here the all of a “text”:
    ========================
    Hi to all,
    feedback for my above post,
    try and try…after work
    is a order list and a modification of “$(function()” from a code in link posted on this forum in the past months:
    —————————————————-
    in

    in

    $.noConflict();
    jQuery(document).ready(function($) {

    /* $(function() { */
    —————————————————-
    Hope is all intended for help.
    Best regards people !

  26. Hi Mary Lou! Tnx for the tutorial, very interesting.
    I’m trying to put menu text in R.BIRD script using your Right Element file.
    Should you help me, please?

  27. Hi Mary Lou, nice script
    Can you send me the script with 4 images, I’m not very good in javascript.
    Thanks in advance
    By

  28. Hi Mary, Thanks so much for sharing such invaluable wisdom.

    Pls, how do I change the dimension from 800X500 to 640 X 300?

    I wouldn’t say am so good with JavaScript but I tried tweekin the code and the images appeared split. Will really appreciate your insight.
    Thanks again for a great tut.

  29. I can’t download the script with 4 images anymore, can someone please upload it and send me too.
    Thanks a lot!

  30. I very much appreciate your work =) I’m putting it to good use at http://annejamin.com

    I modified it to work with 900×600 images. If anybody is interested, come copy my modified script.

    Note: I also modified this line:

    }).attr(‘src’, ‘/images/MP’+i+’.jpg’);

    The “MP” rotates between five variables (sets of images) so you should remove whatever is in the “MP” place when you get to it.

  31. Additional Notes:

    I also removed the (list) elements along with modifying the navigation bar size/position. You’ll want to edit all of that as you see fit. All of that’s fairly simple; the biggest issue I had was getting the larger image size to work and my modifications do that =)

  32. @BANJO; Thanks for the help. I’ve been able to modify the size to my specification. This is a wonderful platform to share insights.
    Thanks y’all. And to Mary, pls don’t stop with the good works.

  33. ok. Can anybody suggest how I can make the links to show on modal windows, without leaving the main page. Will really appreciate any link or suggestion on this pls.
    Thanks

  34. hi, i love the navigation, ive been following the tutorial step by step. but it doesnt seem to be working whn i download the http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js and load it locally. the code doesnt seem to work.
    when copied the javascript and tested it, the navigation doesnt seem to work.

    PLEASE could you help me ive been trying to figure it out, but i am failing. i cant see anything i have missed out in the tutorial.

  35. Does anyone know how to effective change the color images to always slide from the right, no matter where the users mouse comes from?

    I effectively changed the html, css and js to allow 6 menus, but it looks bad when the small color images slide correctly for the first 3 columns and randomly for the last 3.

  36. Figured out the WordPress solution:

    Did what Quantum said:

    (function($){
    The code that was in index.html
    })(jQuery);

    Quantum said:
    “Found this line in index.html
    }).attr(‘src’, ‘images/’+i+’.jpg’);

    Quantum changed it to:
    }).attr(‘src’, ‘/images/’+i+’.jpg’);”

    I changed it to include the absolute path to my images folder:
    }).attr(‘src’, ‘http://www.myurl.com/wp-content/themes/mytheme/images/’+i+’.jpg’);

    Make sure you have the last “/” in the path or it will not work.

  37. Hello, i modified a little bit your script, but i have one problem. When it load menu, first image has incorrect position, but when you hover the second one and then go back on first, it has correct position. I dont understand it, can you help me?
    Here is the source:
    http://www.svkmedia.sk/jt/