Learn and share. The simplest harmony.

 

Auto Moving Submenu Using jQuery

Posted on March 23, 2012 and got 11 shouts so far

Today we’re going to create an automatic moving submenu based on selected its parent. Each submenu is horizontally stacked, sequentially in the order of their parent menu. So when user moving their cursor to the one of parent menu its submenu will appeared by moving its horizontal position.

Creating Menu

First to go is creating menu and its content. Create a div element as menu wrapper, and unordered list element as the menu itself. In this example we’re going to create four menus.




The div will create that wide black block and the unordered list will be positioned on the center of the page with having 870 pixels width.

#menu-wrapper {
	position: relative;
	display: block;
	z-index: 2;
	height: 60px;
   background-image: linear-gradient(to bottom, #535557, #333532);
	font-family: "Pontano Sans";
	font-size: 15px;
	color: #fff;
	text-align: center;
}
	
	.menu {
		display: block;
		margin: 0 auto;
		padding: 0;
		width: 870px;
		text-align: left;
		list-style-type: none;
	}
	
		.menu li {
			display: inline-block;
			padding: 16px 10px 25px 10px;
			cursor: pointer;
			transition: 0.3s ease-in-out;
		}
		
		.menu li:hover, .selected {
			background: #212525;
		}
	
		.menu a, .menu a:visited {
			color: #fff;
			text-decoration: none;
		}


Creating Submenu

Each submenu has their own unordered list that wrapping submenu’s items. Submenu will also contains four items, each will contains image and its title. Each unordered list of submenu will be stacked horizontally. They’re wrapped by div named submenu-wrapper to make us ease to place them.


The submenu wrapper will have similar theme like the parent and also positioned on the center of the page.

#submenu-wrapper {
	position: absolute;
	right: 0;
	left: 0;
	display: block;
	z-index: 1;
	width: 850px;
	height: 130px;
	margin: 0 auto;
	padding: 10px 10px;
	background: rgba(33,37,37,0.9);
	font-family: "Pontano Sans";
	font-size: 13px;
	border-bottom-right-radius: 10px;
	border-bottom-left-radius: 10px;
	box-shadow: 0px 2px 7px rgba(0,0,0,0.5);
}	
	
	.submenu {
		display: block;
		margin: 0 0 1.5em;
		padding: 0;
		list-style-type: none;
	}
	
		.submenu li {
			display: inline-block;
			width: 210px;
			vertical-align: top;
			text-align: center;
		}
		
		.submenu li img {
			display: block;
			margin: 0 auto 1em;
			width: 200px;
			border-radius: 5px;
			border: 0;
		}
		
		.submenu li a, .submenu li a:visited {
			color: #fff;
			text-decoration: none;
		}

Submenu will be like following image :

Show only first unordered list and hide the rest by adding overflow: hidden on #submenu-wrapper.

Since the submenu will appear only when user hovering menu we need to hide them. Set margin top to -12em so the submenu will be show with moving from top to bottom.

jQuery Do The Rest

After all markup was set up now we’ll create some jQuery code to hide and show submenu depend on user interaction to menu and add focus to selected submenu’s item. Before creating that we’ll prepare variables we need later.

menu			= $('.menu li');
submenuWrapper	= $('#submenu-wrapper'); 
submenu			= submenuWrapper.children('ul');
firstSubmenu 	= submenu.eq(0);

firstSubmenu is the first unordered list on submenu stack, we’ll use this variable to move up and down for displaying other unordered list and itself.

Reading Mouse Event

When user hovering their cursor on the menu we’ll check is the submenu has been displayed? if no yet then we’ll animate it. After showing submenu we’ll show appropriate unordered list based on user selection on menu.

menu.hover(
	function() {
		
		moveTo = $(this).index() * 11;
		
		if(!submenuWrapper.hasClass('show'))
			submenuWrapper.addClass('show').stop().animate({'marginTop' : '0'});
			
		firstSubmenu.stop().animate({'marginTop' : '-'+moveTo+'em' });
	},
	
	function() { 
		submenuWrapper.removeClass('show').stop().animate({'marginTop' : '-12em'});
});

If user moving their cursor to submenu it will slide up, to prevent this we also need to attach checking functionality like the menu.

submenuWrapper.hover(
	function() { 
		if(!submenuWrapper.hasClass('show'))
			submenuWrapper.addClass('show').stop().animate({'marginTop' : '0'}); 
	},
	function() { 
		submenuWrapper.removeClass('show').stop().animate({'marginTop' : '-12em'});
});

As you notice we have similar line of code on line 3,4 and 7 as the previous code, we’ll collect them to two functions, showsubmenu and hidesubmenu.

function showsubmenu(item) {
	if(!item.hasClass('show'))
		item.addClass('show').stop().animate({'marginTop' : '0'});
}
	
function hidesubmenu(item) {
	item.removeClass('show').stop().animate({'marginTop' : '-12em'});
}

So the code will be :

menu.hover(
	function() {
		
		moveTo = $(this).index() * 11;
		showsubmenu(submenuWrapper);
		firstSubmenu.stop().animate({'marginTop' : '-'+moveTo+'em' });
},
	
	function() { hidesubmenu(submenuWrapper); 
});
	
submenuWrapper.hover(
	function() { showsubmenu($(this)); },
	function() { hidesubmenu($(this));
});


Adding Focus

Selected submenu item will have a focus by decreasing its siblings opacity. Also add focus on its parent to let user know where they’re at.

submenu
	.children('li')
	.hover(	function() { $(this).siblings().stop().animate({'opacity':'0.5'}); }, 
				function() { $(this).siblings().stop().animate({'opacity':'1'}); });
	

submenu
	.hover(	function() { menu.eq($(this).index()).addClass('selected')  },
				function() { menu.eq($(this).index()).removeClass('selected') });

The focus will work like this :

We’re Done

Yes we’re done, we can also change the animation direction by arranging submenu’s unordered list position. Enjoy!

 

This Post Tags :

Bookmark Post :

Pin It
  • Great !…

  • Good one..!!!

    But does not support IE.

  • Nice Tut. But Siddik is right. Blows up in IE9. Degrades Nicely if no Javascript, but fails on progressive enhancement. We simply cannot ignore IE9…yet. But the concept is so good, that I’m sure some enterprising code-jockey will step up.

    • It works perfectly fine in IE 9!
      The problem is the div#menu-wrapper just needs a background color or image to hide the .submenu.

      Great tutorial!

  • waw , i like this submenu and the move
    its very very nice

    thank you so much
    i hope to get more like this
    speially portfolio

  • Weeee, thats a really good menu .
    I just finished it but i face some difficulties .
    Firstly in idle mode i see the submenu getting up away from the main menu .
    Secondly it does not work on IE :(
    Any idea how to fix that?

    Thanks , and again great work.

  • Ie8 and Ie7 have includes problems. You should do it manually if you want it to work. Follow my example (i didn´t use opacity and focus):

    $(‘#menu li’).hover(
    function() {
    $(‘#submenu-wrapper’).addClass(‘show’).stop().animate({‘marginTop’ : ’0′});
    if(!$(‘#submenu-wrapper’).hasClass(‘show’));
    $(‘#submenu-wrapper’).children(‘ul’).eq(0).stop().animate({‘marginTop’: ‘-’+$(this).index() * 11+’em’ });
    },

    function () {
    $(‘#submenu-wrapper’).removeClass(‘show’).stop().animate({‘marginTop’ : ‘-12em’});
    }
    );

    $(‘#submenu-wrapper’).hover(
    function() {
    $(‘#submenu-wrapper’).addClass(‘show’).stop().animate({‘marginTop’ : ’0′});
    if(!$(‘#submenu-wrapper’).hasClass(‘show’));
    },
    function() {
    $(‘#submenu-wrapper’).removeClass(‘show’).stop().animate({‘marginTop’ : ‘-12em’});
    }
    );

  • this quite nice.

    is it possible to make it so the submenu shows onClick rather than hover?

  • nice menu ! i will use it in my webiste

  • Hello!
    How can I influence the duration of how long the menu is displayed on mouse-out?

  • Only works if you use it at the very top of the page.