From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
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!
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
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.
Mary Lou My case is curious, this menu just work when all the files are in on the paste call “menu” in the domain. When i take this files from this paste and put outside. They just don`t work. What can i do for fix it? Thanks!
You can see here the menu working – http://www.sinttel.org.br/menu/2011.html
and here the very same file width all the corrections to work out of the paste. But simply don’t work.
http://www.sinttel.org.br/2011.html
Hi Marcelo, I think it has to do with your images not being found in the second example. You need to adjust the paths to your images, like e.g. this one does not seem to be right:
http://www.sinttel.org.br/images/1.jpg
Hope it helps,
ML
Hi there,
does anyone know, how to set, which panel opens first?
Thanks
Oh, I’m so bad reader, you have already posted these examples .. sorry 🙂
I noticed that R.RIBRD’S 4 column version has stopped working. Keeps handing out; “TypeError: Result of expression ‘fx.options.curAnim’ [undefined] is not an object.” for the background position…any clues?
example @ http://www.loverspizzeria.com/
Found the issue with R.Bird’s 4 column not working. I guess the api library for “http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js” is probably no longer there….always forget to check that…..
Hello,
Someone can put a zip file with the 5 columns? Because I try it and it never works. I’m not a good webdesigner and I do a website for a friend.
@Mary Lou very good job all you do it’s beautiful. Difficult to choose with all the tuto.
Thanks for help me.
For those that are having issues, especially with R.RIBRD 4 column structure, the google jquery is now at version 1.6.1 which causes an error in the slider. To fix this use this:
http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js
instead of
http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
Hope that helps. I have this running on 2 Joomla websites as a module that is dynamic and loads the standard Joomla menu:
http://www.tenens.com
Cannot give second site as its not live yet!
Lee,
Would you be willing to share the Joomla module? I have been trying to do the same thing but am struggling.
Hi Mary,
Wow! This is really nice. Planning to use this for my website but with the 4 images. I downloaded the zip file. When I tested it out the sliding effect does not work on the original file provided.
Hope you can check it out. Thanks!
I just read Lee’s solution to the problem of the 4 images…it now works.
Thanks Lee!!!!
Very nice effect, but how can i decrease the height of the whole thing? I mean, i need to use smaller images. Same width maybe, but less in height. I just want to adapt the effect. At the moment im getting this big blank space. Thank you.
Hello Mary Lou, congratulations on your work is amazing!
I would like to use your script, the worse I have a question, as it could hide
first submenu and make them only appear when the user place the mouse
above?
Thanks you !
Hello Mary Lou, congratulations for the tutorial.
I have a question: How do you see the second (or third) menu on page load?
Thanks
Can someone help me how to implement this into drupal site which should contain three main navigation ‘News and Events’, ‘Course Announcement’, and ‘About Us’.
except later, other main navigations contain periodically updated contents. User updates somewhere in a place at drupal site and it automatically comes under main navigation.
Thank you.
Please help me.
This is incredible!
Hello,
I will have five links over here. I am trying to edit the position of the first menu to the left but it’s not starting from the edge. I still see some 20px gap at the left. Can some help me to fix it asap? Thanks
By far best slider i have seen!
Hello and well done for your work.
I’m very new at these and i need your help. I did all the html, css and javascript files separately.Then i call css and js files to html. I open html and i get a blank page. What possibly i am doing wrong ? Thank you 🙂
Hi, amazing job Mary Lou. I’ve done a test and the animation doesnt work. I use an old version of jquery (3.2 I think) and still doesnt work. http://friochacon.ucoz.es/index.html
Thanks AMIT DAS for the solution, i was going nuts with the thing not working. For everyone having the problem where the plugin no longer works, change the link code to https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js .
Thanks ML for the work, been using it for more than a year now, superb work.
Very good jquery background image tutorial! Its cool to see flash getting blown away by jquery
Trying to use 8 images (nav elements) within WordPress, but having trouble with maintaining the previous background image. Any help would be appreciated, can be viewed at http://maxwellrowe.com/jf-music-academy
Thanks!
This is a great menu. I managed to correct all the XHTML errors excpet one. Can someone tell me how to make this valid? Thanks. Here is error I receive:
Line 229, Column 14: required attribute “alt” not specified
$(”).load(function(){
?
The attribute given above is required for an element that you’ve used, but you have omitted it. For instance, in most HTML and XHTML document types the “type” attribute is required on the “script” element and the “alt” attribute is required for the “img” element.
Typical values for type are type=”text/css” for and type=”text/javascript” for .
It strips code. 🙁
Hi, how i can make the menus active state. For example when i click on contacts, change background color to red or someting else. May be something like ul.menu li a:active..
but this don’t work
Thanks!
Hi Mary Lou, thank you for your great tutorial.
Can I use this project for my website? In particular, I want to change some parameters and images.
Sorry for my poor english.
Alex
hi,
i have question! how can i add more column with photo’s ? im not realy pro web designer
can someone help me ?
Hi great work!!
Is there a way to hide all sub-menus at first state?
Thanks
Hi everybody! There is a new version which let’s you customize things better:
Sliding Background Image Menu with jQuery
Cheers, ML
jquary 1.5.2 doesnt works on iphone, or did i make a mistake somewhere ?
thx
Hi Mary Lou, you are great !,
You did a nice job, and thank you to share it.
But I had a problem on the keyboard by pressing “ctrl-” because the last slide has been below the other.
Sorry for my poor english, I’m from Spain…
is it possible to do it with more then 3 pictures/ section?
WOW!!! New version is superb! Thanks ML. Gonna mess around a bit with it. TY
Very cool effect. This may come in handy for my upcoming site re-design. Thanks for the post.
This is 1 of the best web portals for jquery. I appreciate the tympanus team for their “Code Creativity”, time and patience. More over I appreciate the team for being very active in the discussions and forums. Good Job.
Great menu slider !!!
Wow…. AWESOME WORK !!!
nice idea
how to show pre-loading image for each slid?
“respectably” not “respectively” when talking about how it works in IE6.
AWESOME AWESOME WORK !
wow awesome effect! thanks!
Hi Mary Lou, thank you for this great tutorial!
I have this working with 6 images here:
http://www.cristiane-festas.ch/
Hi Mary Lou, thanks a ton for this stunning effect.
Further, I would like to use this slider commercially on my website. Please let me know any formalities/legal for the same.
Thanks…..
Great Work
Hi Anmol, thank you, please read our About page: http://tympanus.net/codrops/about/
Cheers, ML
Thanks Mary.
Thanks Team CoDrops.
Hi Mary Lou
Thanks for the jquery effect, brilliant!
Just testing it out on different browsers seems to work fine on all except on the latest IE9.
Is there any coding that can be changed in order to get it working on IE9?
Hi Laura, please check out the new version http://tympanus.net/codrops/2011/07/03/sliding-background-image-menu/
You can do many more things with it! Hope it helps, cheers, ML
Stunning. How can I include a 4th menu into the setup? The original example has three and since I have no Java knowledge, I wouldn’t know where to start.
Please help
I m in love with your work <3
I am new to Web Design and Development, just got a sudden interest into it last month. Such designs are inspirational thanks for the beauty of great designs 🙂