Creating a Dropdown Menu with HTML & CSS

Today we’re going to look at how to make an HTML and CSS dropdown menu. No JavaScript or jQuery required!

Take a look at the demo to test it out and see what the end result looks like. The below HTML and CSS dropdown menu relies on z-index for some of the functionality, which can sometimes trip up beginners. If you get stuck, don’t hesitate to ask me a question.

You might also like: Creating a Responsive Menu with HTML, CSS & jQuery

Table of Contents

  1. Skip to the HTML
  2. Skip to the CSS

1.) HTML Structure

Finished HTML

<div class="menu-wrap">
	<nav class="menu">
		<ul class="clearfix">
			<li><a href="#">Home</a></li>
			<li>
				<a href="#">Movies <span class="arrow">&#9660;</span></a>

				<ul class="sub-menu">
					<li><a href="#">In Cinemas Now</a></li>
					<li><a href="#">Coming Soon</a></li>
					<li><a href="#">On DVD/Blu-ray</a></li>
					<li><a href="#">Showtimes &amp; Tickets</a></li>
				</ul>
			</li>
			<li><a href="#">T.V. Shows</a></li>
			<li class="current-item"><a href="#">Photos</a></li>
			<li><a href="#">Site Help</a></li>
		</ul>
	</nav>
</div>

Ek Mukta Font

If you would like to use the same font as I’ve used you need a link to it in the header.

<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Ek+Mukta">

Wrapper and Nav

We start off with a wrapper div and give it a class of menu-wrap. Inside that wrapper, we put a nav and give it a class of menu.

<div class="menu-wrap">
	<nav class="menu">
		<!-- NAV -->
	</nav>
</div>

First Unordered List

The first unordered list we’ll be using needs a class of clearfix (more on why when we write the CSS). Inside it, we’ll put a couple of links to act as menu content.

<ul class="clearfix">
	<li><a href="#">Home</a></li>
	<li><a href="#">Movies <span class="arrow">&#9660;</span></a></li>
	<li><a href="#">T.V. Shows</a></li>
	<li class="current-item"><a href="#">Photos</a></li>
	<li><a href="#">Site Help</a></li>
</ul>

Nested Dropdown Menu

For the dropdown menu, we put another unordered list inside the one we already have and the HTML code is complete.

<ul class="clearfix">
	<li><a href="#">Home</a></li>
	<li>
		<a href="#">Movies <span class="arrow">&#9660;</span></a>

		<ul class="sub-menu">
			<li><a href="#">In Cinemas Now</a></li>
			<li><a href="#">Coming Soon</a></li>
			<li><a href="#">On DVD/Blu-ray</a></li>
			<li><a href="#">Showtimes &amp; Tickets</a></li>
		</ul>
	</li>
	<li><a href="#">T.V. Shows</a></li>
	<li class="current-item"><a href="#">Photos</a></li>
	<li><a href="#">Site Help</a></li>
</ul>

2.) CSS Styling

Finished CSS

body {
	background:#bf5c71 url('body-bg.jpg');
}

.clearfix:after {
	display:block;
	clear:both;
}

/*----- Menu Outline -----*/
.menu-wrap {
	width:100%;
	box-shadow:0px 1px 3px rgba(0,0,0,0.2);
	background:#3e3436;
}

.menu {
	width:1000px;
	margin:0px auto;
}

.menu li {
	margin:0px;
	list-style:none;
	font-family:'Ek Mukta';
}

.menu a {
	transition:all linear 0.15s;
	color:#919191;
}

.menu li:hover > a, .menu .current-item > a {
	text-decoration:none;
	color:#be5b70;
}

.menu .arrow {
	font-size:11px;
	line-height:0%;
}

/*----- Top Level -----*/
.menu > ul > li {
	float:left;
	display:inline-block;
	position:relative;
	font-size:19px;
}

.menu > ul > li > a {
	padding:10px 40px;
	display:inline-block;
	text-shadow:0px 1px 0px rgba(0,0,0,0.4);
}

.menu > ul > li:hover > a, .menu > ul > .current-item > a {
	background:#2e2728;
}

/*----- Bottom Level -----*/
.menu li:hover .sub-menu {
	z-index:1;
	opacity:1;
}

.sub-menu {
	width:160%;
	padding:5px 0px;
	position:absolute;
	top:100%;
	left:0px;
	z-index:-1;
	opacity:0;
	transition:opacity linear 0.15s;
	box-shadow:0px 2px 3px rgba(0,0,0,0.2);
	background:#2e2728;
}

.sub-menu li {
	display:block;
	font-size:16px;
}

.sub-menu li a {
	padding:10px 30px;
	display:block;
}

.sub-menu li a:hover, .sub-menu .current-item a {
	background:#3e3436;
}

Base Styling

We start the CSS with some base styling by setting a page background colour and setting up a clearfix. Don’t worry if you don’t have the background image it’s only a simple texture. You can grab it from the demo if needed.

The clearfix will stop an annoying bug where, if a parent element has a floated child element, it will disappear.

body {
	background:#bf5c71 url('body-bg.jpg');
}

.clearfix:after {
	display:block;
	clear:both;
}

Menu Setup

Now we need to set up the outline of the entire menu and style a few ‘global’ elements (two or more elements with the same styling).

/*----- Menu Outline -----*/
.menu-wrap {
	width:100%;
	box-shadow:0px 1px 3px rgba(0,0,0,0.2);
	background:#3e3436;
}

.menu {
	width:1000px;
	margin:0px auto;
}

.menu li {
	margin:0px;
	list-style:none;
	font-family:'Ek Mukta';
}

.menu a {
	transition:all linear 0.15s;
	color:#919191;
}

.menu li:hover > a, .menu .current-item > a {
	text-decoration:none;
	color:#be5b70;
}

Dropdown Arrow

The arrow by default is quite large so we make the font-size smaller and remove the line-height. If we leave the default line-height the menu styling may become affected.

.menu .arrow {
	font-size:11px;
	line-height:0%;
}

Top Level Menu

To style just the top-level menu we can use the > symbol. It states that only the first child element preceding the parent will get the specified styling. E.g. .parent > child, only the top-level .child will get the styling whereas any children of .child that are also called .child won’t.

We also set a position:relative; on the parent list item in case it has a child (aka a submenu).

/*----- Top Level -----*/
.menu > ul > li {
	float:left;
	display:inline-block;
	position:relative;
	font-size:19px;
}

.menu > ul > li > a {
	padding:10px 40px;
	display:inline-block;
	text-shadow:0px 1px 0px rgba(0,0,0,0.4);
}

.menu > ul > li:hover > a, .menu > ul > .current-item > a {
	background:#2e2728;
}

Bottom Level Menu

Here’s the fun part…and also the main point of this article. To style the sub menu we first need to position it. We do that with position:absolute;. By setting a percentage as the top instead of a fixed pixel value the submenu will always be positioned exactly at the bottom of its parent.

We also add z-index:-1;. This pushes the dropdown menu behind the everything else on the page, including the body element.

There’s also no opacity, this is so the submenu can fade in by using a transition.

For the transition you may want to use prefixed values if you’re targeting older browsers, however, for the purposes of this tutorial, we’ll be aiming at Firefox and Webkit based browsers (Webkit browsers include Google Chrome and Opera).

You may also wonder what the rgba(0,0,0,0.2) is. It states a colour (Red, Green and Blue) then the opacity (Alpha), in this case, it’s 20% (0.2)

/*----- Bottom Level -----*/
.sub-menu {
	width:160%;
	padding:5px 0px;
	position:absolute;
	top:100%;
	left:0px;
	z-index:-1;
	opacity:0;
	transition:opacity linear 0.15s;
	box-shadow:0px 2px 3px rgba(0,0,0,0.2);
	background:#2e2728;
}

To get the dropdown menu showing on hover we need to add a line that states when hovering over a list item, show its children. This has no effect on empty list items as they have no children to show.

.menu li:hover .sub-menu {
	z-index:1;
	opacity:1;
}

The rest is the styling of the submenu list items and anchor links.

.sub-menu li {
	display:block;
	font-size:16px;
}

.sub-menu li a {
	padding:10px 30px;
	display:block;
}

.sub-menu li a:hover, .sub-menu .current-item a {
	background:#3e3436;
}

Conclusion

Some of the CSS used may be a little hard to wrap your head around at first, especially if you’re a beginner. If you need help in any way create a JSFiddle of your code and post the link to it in the comments.

Thank you for reading and I look forward to chatting with you below!

You might also like: Creating an Accordion with HTML, CSS & jQuery

ResourceA Beginner’s Guide to HTML in Web Development.


Comments

Leave a Comment

Comments (158)

Fred

July 26, 2018 at 6:36 pm

Hello all, first off, nice piece and nice explanation. But please I have been having problem getting my drop-down contents showing on hover, I’ve gone to hell and back without luck, it’s just permanently hidden under the movies menu and never comes out…. Please HELP!!!

Reply

Mark

May 31, 2018 at 1:03 pm

Excellent. I have picked up a lot of stuff I have previously forgotten. Good work. I want to see how to make this responsive now with a hamburger menu and with the submenu included.

Reply

Derrick

April 15, 2018 at 11:16 am

How do I start a CSS after html by coding dropmenu

Reply

NoobishUser

January 24, 2018 at 11:18 pm

Thank you!

Helped me out! Best wishes to you man!!!

Best

Reply

xmllllll

January 16, 2018 at 1:35 pm

Hi,
I tied to put the navigation bar in the center but failed to do so. I have try to use padding 0 30% but when I resize my window the navigation won’t be in the center. tried to use text-align and margin 0 auto, all not working. appreciate anyone can help.

Thanks.

Reply

xmlllll

January 16, 2018 at 1:30 pm

Hi I have difficulties to align the navigation bar centre. I tried several ways put padding-left, but when I resize the windows the navigation not centred anymore. I tried use margin: 0 auto; text-align all not working. appreciate anyone can help. thanks

Reply

Jason

November 22, 2017 at 10:14 pm

Hello,
Thank you for taking the time to show us how to create this. I am an elementary school teacher who is trying to learn to code on my own. I am not happy with any of the websites out there that I have found to use for my classroom. I have decided to take it upon myself to learn to code and create a website that all teachers can use and love.

Reply

Inspirational Newsletter


Join the newsletter to get the best articles, tutorials and exclusive freebies every two weeks.

No spam. You can unsubscribe at any time.