Horizontal Drop-Down Menu

A responsive horizontal drop-down menu inspired by the Microsoft.com menu.

Horizontal Drop-Down Menu

From our sponsor: Try Mailchimp today.

This large horizontal drop-down menu simply shows the sub-menu when an item gets clicked. It’s inspired by the Microsoft.com drop-down menu. Some example media queries show how to adjust the menu for smaller screens.

The HTML

<nav id="cbp-hrmenu" class="cbp-hrmenu">
	<ul>
		<li>
			<a href="#">Products</a>
			<div class="cbp-hrsub">
				<div class="cbp-hrsub-inner"> 
					<div>
						<h4>Learning & Games</h4>
						<ul>
							<li><a href="#">Catch the Bullet</a></li>
							<li><a href="#">Snoopydoo</a></li>
							<!-- ... -->
						</ul>
					</div>
					<div>
						<h4>Utilities</h4>
						<ul>
							<li><a href="#">Gadget Finder</a></li>
							<li><a href="#">Green Tree Express</a></li>
							<li><a href="#">Green Tree Pro</a></li>
							<li><a href="#">Wobbler 3.0</a></li>
							<li><a href="#">Coolkid</a></li>
						</ul>
					</div>
					<div>
						<!-- ... -->
					</div>
				</div><!-- /cbp-hrsub-inner -->
			</div><!-- /cbp-hrsub -->
		</li>
		<li><!-- ... --></li>
		<li><!-- ... --></li>
		<!-- ... -->
	</ul>
</nav>

The CSS

.cbp-hrmenu {
	width: 100%;
	margin-top: 2em;
	border-bottom: 4px solid #47a3da;
}

/* general ul style */
.cbp-hrmenu ul {
	margin: 0;
	padding: 0;
	list-style-type: none;
}

/* first level ul style */
.cbp-hrmenu > ul,
.cbp-hrmenu .cbp-hrsub-inner {
	width: 90%;
	max-width: 70em;
	margin: 0 auto;
	padding: 0 1.875em;
}

.cbp-hrmenu > ul > li {
	display: inline-block;
}

.cbp-hrmenu > ul > li > a {
	font-weight: 700;
	padding: 1em 2em;
	color: #999;
	display: inline-block;
}

.cbp-hrmenu > ul > li > a:hover {
	color: #47a3da;
}

.cbp-hrmenu > ul > li.cbp-hropen a,
.cbp-hrmenu > ul > li.cbp-hropen > a:hover {
	color: #fff;
	background: #47a3da;
}

/* sub-menu */
.cbp-hrmenu .cbp-hrsub {
	display: none;
	position: absolute;
	background: #47a3da;
	width: 100%;
	left: 0;
}

.cbp-hropen .cbp-hrsub {
	display: block;
	padding-bottom: 3em;
}

.cbp-hrmenu .cbp-hrsub-inner > div {
	width: 33%;
	float: left;
	padding: 0 2em 0;
}

.cbp-hrmenu .cbp-hrsub-inner:before,
.cbp-hrmenu .cbp-hrsub-inner:after {
	content: " ";
	display: table;
}

.cbp-hrmenu .cbp-hrsub-inner:after {
	clear: both;
}

.cbp-hrmenu .cbp-hrsub-inner > div a {
	line-height: 2em;
}

.cbp-hrsub h4 {
	color: #afdefa;
	padding: 2em 0 0.6em;
	margin: 0;
	font-size: 160%;
	font-weight: 300;
}

/* Examples for media queries */

@media screen and (max-width: 52.75em) { 

	.cbp-hrmenu {
		font-size: 80%;
	}

}

@media screen and (max-width: 43em) { 

	.cbp-hrmenu {
		font-size: 120%;
		border: none;
	}

	.cbp-hrmenu > ul,
	.cbp-hrmenu .cbp-hrsub-inner {
		width: 100%;
		padding: 0;
	}

	.cbp-hrmenu .cbp-hrsub-inner {
		padding: 0 2em;
		font-size: 75%;
	}

	.cbp-hrmenu > ul > li {
		display: block;
		border-bottom: 4px solid #47a3da;
	}

	.cbp-hrmenu > ul > li > a { 
		display: block;
		padding: 1em 3em;
	}

	.cbp-hrmenu .cbp-hrsub { 
		position: relative;
	}

	.cbp-hrsub h4 {
		padding-top: 0.6em;
	}

}

@media screen and (max-width: 36em) { 
	.cbp-hrmenu .cbp-hrsub-inner > div {
		width: 100%;
		float: none;
		padding: 0 2em;
	}
}

The JavaScript

var cbpHorizontalMenu = (function() {

	var $listItems = $( '#cbp-hrmenu > ul > li' ),
		$menuItems = $listItems.children( 'a' ),
		$body = $( 'body' ),
		current = -1;

	function init() {
		$menuItems.on( 'click', open );
		$listItems.on( 'click', function( event ) { event.stopPropagation(); } );
	}

	function open( event ) {

		if( current !== -1 ) {
			$listItems.eq( current ).removeClass( 'cbp-hropen' );
		}

		var $item = $( event.currentTarget ).parent( 'li' ),
			idx = $item.index();

		if( current === idx ) {
			$item.removeClass( 'cbp-hropen' );
			current = -1;
		}
		else {
			$item.addClass( 'cbp-hropen' );
			current = idx;
			$body.off( 'click' ).on( 'click', close );
		}

		return false;

	}

	function close( event ) {
		$listItems.eq( current ).removeClass( 'cbp-hropen' );
		current = -1;
	}

	return { init : init };

})();

Tagged with:

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

Feedback 111

Comments are closed.
  1. Nice – can it be set to hover by changing ‘click’ references to ‘hover’?

    • Dan, have a look at this. Without giving the answer away on quite a simple solution, I say “why not take a stab at a few of these events?” 🙂

      Definitely not too hard to figure out at all. I’m a JS n00b, and still got it right away.

    • I tried the same, but it won’t work. Try to use mouseover or mouseenter. But since I am not good with this either, I can’t figure out a way to let it stay open when using the actual submenu but to close when moving somewhere else.

    • I couldn’t get it to work with changing the click event to hover. I’ll try the mouse enter event next.

  2. Good job, really awesome – clean and professioanal.

    I have a question – is it possible to close menu when user clicks somewhere outside of the menu area?

  3. Quick question, once integrated into my site the drop down does not move the rest of the page content down with it? Any ideas how to get this to work?

    • Hi – did you find a fix for this?

      I’m having the same issue with the content not being pushed down when the menu’s open.
      Also some of the elements below the nav menu are displaying on top of the open menu (slider/ buttons). See: http://bit.ly/YbBCsf

      Thanks

    • I wasn’t able to force the other elements down upon open, however I managed to get it to display over the top of them. If anyone else is wondering how to do this, you just need to add:

      z-index: 99999;

      to the following class:

      .cbp-hropen .cbp-hrsub {

    • Hey have you found a fix for this? It would be amazing to bump the whole content down. I was thinking of using the Js from the slide and push menu but know very little about JS. Any ideas anyone?

    • I haven’t I’m afraid.. I’ve stuck with adding z-index and allowing the menu to appear over the top of other content. I agree with you however, would be better if the content was pushed down

  4. A life saver! needed the same logic for a similar menu am coding fro scratch, with minor differences 🙂 thank u 🙂

  5. may help for hover seems much easier if you just do this….

    $(“#cbp-hrmenu > ul > li”).hover(
    function(){
    $(this).addClass(“cbp-hropen”);
    },function(){
    $(this).removeClass(“cbp-hropen”);
    }
    );

    • He’s saying you can replace the current script with this. It will achieve the affect but with hovering instead of clicking the links. I’ve not tested this on all browsers but it seems to work well in chrome.

    • Why should U change the original oop code? Isn’t easier to change this line from this
      $menuItems.on( 'click', open );
      to this
      $menuItems.on( 'mouseover', open );
      in order to get the mouse over effect? 🙂

    • I have the same restlessness, someone
      has accomplished, when you have sub items, that when clicking on the option to take me to the url indicated

      Thank you.

    • Got it:

      I found a way.

      For any menu item I want to use as a drop-down, I gave it a new class:
      <a href=”#” rel=”nofollow”>Dropdown Link</a>

      Then changed this line in the js:
      var b=$(“#cbp-hrmenu > ul > li”)
      … to …
      var b=$(“#cbp-hrmenu > ul > li.dropdown”)

      This turns all top-level links into direct links unless specifically marked for drop-down.

  6. Hi, love the drop down. Is it possible to make a menu item a link to another page though, rather than a drop down menu?

    • Hi, figured it out. Basically what I did was take out all the menu options that weren’t supposed to be a drop down and created another nav class that looked the exact same as the drop down menu one. Put that in a list with proper ul li properties and it’ll all line up and it’ll act like a normal menu!

    • Hi Michael,

      Could you please explain what you done exactly? The only solution I see is to create a whole new nav menu that sits to the side of this one, but in doing so we’d then need to change the ‘width: 100%;’ to a fixed width in pixels. Eg if we’re using a 940px width, give the main nav menu 900px, then the remaining 40px can be used for the additional nav menu (with a clickable link). This means the menu’s no longer responsive.

      I’m guessing you’ve found a more suitable way around this.. would be great if you could share your solution with us 🙂

      Cheers

  7. Hey guys. Thanks for this!

    I have a problem though. This does not seem to work in IE 7 or 8. Is there a fix I can apply to hack those browsers into a working state?

  8. Hello, how can i make it a vertical menu? and to reduce the drop box dimensions?

  9. Hi,
    I’m trying to add a jquery-ui effect to the dropdown, however, the .removeClass doesn’t seem to be working..
    Can anyone shed any light on this!?
    I’ve put together a to show the effect..

  10. Good job, i love it, but…

    …I have a question!

    when user clicks somewhere outside of the menu area it closes instantly… i want to leave it always open and i’m trying but cant afford that yet. someone want to help me please?!

    • Hi Pedro, just comment/remove this line:
      $body.off( ‘click’ ).on( ‘click’, close );
      Hope it helps. Cheers, ML

  11. im using it for an admin backoffice (for a school work) and when i do action on it it automatic close. i resolve it with some php, i turned off the jquery and do

    if (!isset($_SESSION[‘menu’]))
    $_SESSION[‘menu’]=1;

    if (isset($_GET[‘m’]))
    $_SESSION[‘menu’]=$_GET[‘m’];

    and then

    <a href=”principal.php?m=1″ rel=”nofollow”>Sobre Mim</a>

    Problem solved it will be always open when working on the content of the tab!!!

  12. Hello,

    First of all congratulations for this wonderful work and the valuable help you make the developer.

    I have a question about this wonderful menu that I would like to integrate into a website project.

    How to restrict the width of the menu placed in a wrapper 1200px?

    Alas, I am not come, can you help me?

    Thank you for all the resources and help.

    Very good job.

  13. Hi,
    This is beautiful. Has anyone figured out how to keep top menu highlighted when child elements are hovered on?
    Thank you,

  14. Hey..

    I was just wondering.. How can I edit this in order to make it close when an element of the drop menu is clicked?

    Is this possible?

    Thanks in advance.

    • Well I think I fixed it but im using the menu is two locations of the same page.. It works for one but the other one doesnt seem to be affected how ever I try and change the code.

      What I did,
      $mylistItems = $( ‘.cbp-hrsub-inner > ul li’ ),
      $mymenuItems = $mylistItems.children( ‘a’ ),

      Added the above code at the start so I can focus on the items that are been clicked and then gave an click event for them. $mymenuItems.on(‘click’ , close);

      I tried changing the elements around because I had an extra div in my second instance of the menu. This didnt actually help though.

      Month tag

    • Well I cant actually post my code. Just realized I cant delete any of those posts also .. sigh ..

  15. Hi,

    when you set an z-index to .cbp-hrmenu .cbp-hrsub you will not have problems with absolute positioned elements on your side.

  16. This is a great tutorial but I feel like the mock up is far too complicated for trying to teach a dog new tricks- would love to see this simplified into a more simple drop down for the sake of learning.

  17. This is great — does all that I want but… I have some top-level menu items that do not have sub menus. How can I get those links to ignore the js and go directly to the url link?

    • Change the $listItems selector in the JS to only attach the menu code to those with submenus. This should work:
      $listItems = $( '#cbp-hrmenu > ul > li' ).has('ul')

    • Actually, it would probably be better to use:
      $listItems = $( '#cbp-hrmenu > ul > li' ).has( '.cbp-hrsub' )

      That way, you can have a submenu that doesn’t have a ul in it.

    • Thankyou Sunny!
      This worked great, but now my styling is gone. Is that something that should be done in the js or the css.
      I’m trying to get the parent tabs to stay highlighted when a child page is active. I don’t know if this is something that worked initially and I broke it or it’s not coded in. Does this make sense to anyone?

  18. Would there be anyway this could be used with WordPress? I would love to add this to a WordPress site.

    Thanks!

  19. Hi,

    I see a few people on here are wondering how to create the menu but have some of the top level menu items that don’t have drop down content as normal menu links that would take you away from the page.

    Has anyone discovered how to do this yet? I was trying to follow Evin’s example in the comments but this was not working for me.

    Any help would be greatly appreciated!

    Thanks in advance.

    • Hi Ronan,

      This could be done easily:

      In the JS, change $menuItems = $listItems.children( 'a' ), to $menuItems = $listItems.children( 'a.dropdown' ),

      In the HTML, change <a>MyHyperLink</a> to <a href="#" rel="nofollow">MyHyperLink</a> wherever you need a dropdown

      This will fix your issue and make nav items without subitems clickable and take you to the new page

      Regards,
      Steven

    • Format gone, sorry for that!

      Just do as described for the JS part

      In the HTML, change a href to a class="dropdown" href wherever you have subitems and need a dropdown.

      Regards,
      Steven

    • Hi StevenCM,

      Thank you very much for that, apologies I am a beginner with JS, it worked perfectly!!

      Thanks again!

  20. I have litlle code that does same.

    $( ‘#cbp-hrmenu > ul > li’ ).click(function(){
    $( ‘#cbp-hrmenu > ul > li’ ).removeClass( ‘cbp-hropen’ );
    $(this).addClass(‘cbp-hropen’);
    });

  21. I try with this code and works good, but…:
    $(function() { var $oe_menu = $('#cbp-hrmenu'); var $oe_menu_items = $oe_menu.children('li'); var $oe_overlay = $('#oe_overlay'); $oe_menu_items.bind('mouseenter',function(){ var $this = $(this); $this.addClass('slided selected'); $this.children('div').css('z-index','9999').stop(true,true).slideDown(200,function(){ $oe_menu_items.not('.slided').children('div').hide(); $this.removeClass('slided'); }); }).bind('mouseleave',function(){ var $this = $(this); $this.removeClass('selected').children('div').css('z-index','1'); }); $oe_menu.bind('mouseenter',function(){ var $this = $(this); $oe_overlay.stop(true,true).fadeTo(200, 0.6); $this.addClass('hovered'); }).bind('mouseleave',function(){ var $this = $(this); $this.removeClass('hovered'); $oe_overlay.stop(true,true).fadeTo(200, 0); $oe_menu_items.children('div').hide(); }) });

    CSS:
    .oe_overlay{ background:#000; opacity:0; position:fixed; top:0px; left:0px; width:100%; height:100%; }

    … it’s ok for desktop browser, but with touch screen (table, smartphone), not works… the dark background overlay remain open when close the panel.

    Any tips/suggestions?

  22. Hey everyone.
    I have big problem with this blueprint. Everythings looks work fine but when i try implement this in my website like this :
    <a href="#" rel="nofollow">Products</a> Learning & Games <a href="#" rel="nofollow">Catch the Bullet</a> <a href="#" rel="nofollow">Snoopydoo</a> <!-- ... --> Utilities <a href="#" rel="nofollow">Gadget Finder</a> <a href="#" rel="nofollow">Green Tree Express</a> <a href="#" rel="nofollow">Green Tree Pro</a> <a href="#" rel="nofollow">Wobbler 3.0</a> <a href="#" rel="nofollow">Coolkid</a> <!-- ... --> <!-- /cbp-hrsub-inner --> <!-- /cbp-hrsub --> <!-- ... --> <!-- ... --> <!-- ... -->
    Nothing work and firebug dont show me any problems. Inside runmenu.js i put
    $(document).ready(function() { cbpHorizontalMenu.init(); });

    any help ?

  23. Note that the code to close the menu on a body click is destructive. If you have any other click events on the body, this code will break those other events.

    By name spacing the click events on the body, this can be avoided.

    Offending code: $body.off( 'click' ).on( 'click', close );

    Fixed code: $body.off( 'click.cbphr' ).on( 'click.cbphr', close );

  24. To make this menu show and hide on hover. Give each #cbp-hrmenu > ul > li a unique id and then do the following jquery –
    <script> var $listItems = $( '#cbp-hrmenu > ul > li' ); $listItems.hover(function() { var id = $(this).attr('id'); var t = setTimeout(function(){ $('#'+id).addClass( 'cbp-hropen' ); }, 200); }, function() { var id = $(this).attr('id'); var t = setTimeout(function(){ $('#'+id).removeClass( 'cbp-hropen' ); }, 300); }); <script>

  25. Hola Mary Lou, te agradezco mucho por iluminarnos con tus desarrollos, implementare este menú en un sitio web, si gustas luego te envió el link.

    Buenas Noches!

  26. This is a very neat drop-down menu, just one thing is essential
    if there is a main menu item with no children it will need to be a link to some page

    I recommend changing the code when defining the variables to only contain those with nested unordered lists like this

    var $listItems = $( ‘#cbp-hrmenu > ul > li’ ).has(‘ul’),

    Best

  27. Mary Lou,
    Kudos on the beautiful click and stick menu! I love it.
    I would love to get it to work on my site. I’m having some difficulty with the active tab maintaining the blue background. The input for the zindex and how to get the parent without a child to work as a link, etc. was so helpful … thank you guys! I’m a newbie to query. So I’m wondering if there is a tutorial out there that walks through the code. Or a demo with more than just the index page since I can’t look at the code and know if the link is supposed to remain active or if it’s something I broke in the process of augmenting it. Or if someone that got it to work would post a link to their site? I would be most grateful. Thank you <3

  28. All I get after installing everything is this error – ReferenceError: $ is not defined. It looks fine but no menus open up.

  29. What I don’t understand is the reason why you put, in the default.css file, the following definition:

    .icon-drop:before {
    […]
    text-indent: 8000px;
    […]
    }

    This seems to work in Chrome and Firefox, but not in Opera, Safari etc…
    Thanks for any explanations!
    Marco

  30. Would someone please share the code with me for closing the submenu when a submenu link is clicked? Thanks!

  31. Hi! Great job!

    Could anyone tell me how to keep one of the drop menus (the first one, for example) open “on page load” so I can make it the first presentation page?

    Thanks in advance.

    • Yes I would like to know how to do this too. I have switched click to mouseover however it needs more code than that like timeout..and how it mouses out.. I have a large subnav like the one shown on this demo. Please help!

  32. I just installed this beautiful jquery responsive horizontal menu bar for my empty webpage. The menubar has not been altered with any style or modification by me.

    Can anyone help me to:

    Keep the submenu to the width of my blue border (horizontal rule)–container width in Deskview. Currently when the submenu opens it expands and fills the whole width of the screen across. I would like it to show only within my container. (Even with the blue border line).

    When resizing the screen to mobile size, it looks great as it is (and thats how I want it exactly)–Like the mobile.–When you resize back to desk it has a different look (outside the container / blue boder-horiz rule)

    When styling this menu bar previously, It would seem that every change I would make in deskview to fix the problem, would create a new problem in mobileview. Mobileview of this menubar is PERFECT!–I need Desk to look like the mobile (even with the blue border line).

    Any help would be greatly appreciated. Thank you

    Here is the site / code:

    http://www.dothopper.com

  33. This is a beautiful menu btw, thanks very much Mary Lou.

    When I view my menu on Android and iphone, the menu is in the full open position showing all parent and children list items. My menu will be somewhat large, so this could be an issue. When I am styling it with my WYSIWIG editor, it looks like it will only show the Parents (no child items), but when I view it live on browser, it is open, exposing all parent and child items, and will not close.

    Is this the default? Am I doing something wrong? If so, is there a way to collapse the child items?

    Also, I found this code to ‘toggle’ a responsive menu:

    $(“.toggleMenu”).click(function(e) {
    e.preventDefault();
    $(“.nav”).toggle();
    });
    if (ww < 800) {
    $(".toggleMenu").css("display", "inline-block");
    $(".nav").hide();
    } else {

    }

    I have tried to use this (unsuccessfully) to ‘toggle’ the menu trying to create a ‘hamburger-style’ icon to then reveal Parent items.

    Is there any way to get this to work?

    Thanks very much for any help

  34. Hi,
    very good job, nice menu!
    i changed the onclick event to onmouseover
    is there a possibility to delay the mouseover event for lets say 0.5 secondes?
    thanks in advance