You can find a lot of different menu styles on the web today. Similarly designers and developers are often more than happy to share their techniques with the world. And through these tutorials new designers can learn about trends and how to build websites semantically.
In this tutorial I want to demonstrate how we can build a simple HTML5 user dropdown menu. This will contain links for a typical user profile which are only displayed through a jQuery sliding animation. Note that you could replicate this animation using CSS3, but JavaScript has a much wider support among browsers. Also the CSS effects can appear more choppy than rendering through jQuery animations.
So without further ado let’s jump right into the code! If you want to check out my live demo you can see this from the link below. Or additionally download a copy of my source code to work with as you read through the article.
Live Demo – Download Source Code
Contents
Getting Started
Let’s first create the core files we will need in this tutorial. I am using a single index.html
file along with separate CSS code inside styles.css
. Our page is built running on the HTML5 doctype along with some additional header resources.
<!doctype html> <html lang="en-US"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title>User Settings Dropdown Menu</title> <meta name="author" content="Jake Rocheleau"> <link rel="shortcut icon" href="http://teamtreehouse.com/favicon.ico"> <link rel="icon" href="http://teamtreehouse.com/favicon.ico"> <link rel="stylesheet" type="text/css" href="styles.css"> <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Oldenburg"> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <!--[if lt IE 9]> <script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head>
Aside from the Treehouse favicon I have also included two other 3rd party documents. The first is a custom font by Google which I’ve applied onto the header text. Secondly I am referencing the most recently updated version of jQuery and the popular HTML5shiv script for older Internet Explorer users. This allows us to use HTML5 elements such as <header>
without facing rendering issues down the line.
Structuring the Dropdown
The page HTML is actually very compact and easy to follow. I haven’t included any other content aside from the single dropdown menu. Also the links have been edited to disable href values, but you can change these to whatever suits your website.
<div id="wrap"> <h1>Stylish User Settings Menu</h1> <div id="dropdown" class="ddmenu"> User Settings <ul> <li><a href="#">My Profile</a></li> <li><a href="#">Friend Requests</a></li> <li><a href="#">Account Settings</a></li> <li><a href="#">Support</a></li> <li><a href="#">Log Out</a></li> </ul> </div> </div>
So the container element is a single div with the ID #dropdown
. Inside I have some plain text which is displayed normally, along with an inner UL element. This unordered list will behave as our real set of menu links, since the select menu shouldn’t ever lead anywhere.
Each link is placed inside a list item and will automatically adjust based on the menu height. You can actually edit many of these styles inside the CSS document, along with positioning. Let’s dive into that code now.
Most of my code starts off with a similar block of CSS resets based on Eric Meyer’s infamous snippet. I’ve included some custom styles on the page body, along with h1 tags and paragraphs. Images are also set to max-width: 100%;
so that all page content is dynamic and responsive.
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; outline: none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html { height: 101%; } body { background: #dde9f0 url('images/bg.png'); font-family: Arial, Tahoma, sans-serif; font-size: 62.5%; line-height: 1; padding-bottom: 65px; } article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } strong { font-weight: bold; } table { border-collapse: collapse; border-spacing: 0; } img { border: 0; max-width: 100%; } h1 { display: block; font-size: 2.75em; line-height: 2.35em; color: #7291a5; margin-bottom: 12px; font-weight: normal; font-family: 'Oldenburg', 'Trebuchet MS', Arial, sans-serif; text-shadow: 0px 1px 1px #fff; text-align: center; } p { font-size: 1.2em; font-weight: normal; line-height: 1.35em; color: #343434; margin-bottom: 12px; }
Now the dropdown menu is utilizing a lot of CSS3 properties. I have a simple box shadow on the outside of our container and the unordered list. But I am also using a very brief transition effect when the menu goes from closed to open, and vice-versa. This will animate a brief text & background color change over 150 milliseconds.
/* user menu settings */ #dropdown { display: block; padding: 13px 16px; width: 266px; margin: 0 auto; position: relative; cursor: pointer; border-left: 4px solid #739cda; background: #fff; font-size: 1.55em; color: #656565; font-weight: normal; -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.3); -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.3); box-shadow: 1px 1px 2px rgba(0,0,0,0.3); -webkit-transition: all 0.15s linear; -moz-transition: all 0.15s linear; -ms-transition: all 0.15s linear; -o-transition: all 0.15s linear; transition: all 0.15s linear; } #dropdown:hover { color: #898989; } #dropdown.open { background: #5a90e0; color: #fff; border-left-color: #6c6d70; }
You’ll notice I have setup a fixed width value for the menu container. This is helpful especially if you have limited free space in your layout. This effect will always work best if you can put constraints on the content width. Additionally I am using the position: relative;
property so that our internal UL may be positioned absolutely.
The final puzzle piece is resizing and scaling all the internal menu anchor links. All of the text should be resized using relative ems since all of our other fonts are scaled in the same way.
#dropdown ul { position: absolute; top: 100%; left: -4px; /* move content -4px because of container left border */ width: 266px; padding: 5px 0px; display: none; border-left: 4px solid #8e9196; background: #fff; -webkit-box-shadow: 1px 1px 2px rgba(0,0,0,0.3); -moz-box-shadow: 1px 1px 2px rgba(0,0,0,0.3); box-shadow: 1px 1px 2px rgba(0,0,0,0.3); } #dropdown ul li { font-size: 0.9em; } #dropdown ul li a { text-decoration: none; display: block; color: #447dd3; padding: 7px 15px; } #dropdown ul li a:hover { color: #6fa0e9; background: #e7f0f7; }
Also I am positioning the menu with left: -4px
because of a small quirk we get with the container border. Since the dropdown div has a 4px left border this means all internal content is pushed out 4 pixels using the border-box
sizing value. But since our menu is positioned absolutely this minute change doesn’t affect our document flow whatsoever.
I have setup the same width and box shadow values on our internal UL element so the boxes appear to match. You could theoretically extend the width of the internal menu so it takes up more space, but that would also require updating the z-index property and handling possible interactions with other page elements.
The Sliding Animation
Now that we have seen all the fancy HTML/CSS code for putting together this menu let’s get it to work. The JavaScript we need is very basic so I have just placed a <script>
tag at the bottom of my closing </body>
tag. But alternatively you may create an external .js file and it should all work out the same.
$("#dropdown").on("click", function(e){ e.preventDefault(); if($(this).hasClass("open")) { $(this).removeClass("open"); $(this).children("ul").slideUp("fast"); } else { $(this).addClass("open"); $(this).children("ul").slideDown("fast"); } });
So whenever a user clicks on the dropdown menu we call a new internal function, passing in the parameter function(e)
to handle the click event. The code e.preventDefault()
will stop all anchor links from loading their href value. I have only done this for our demo but you can remove this on a real website deploy.
The rest of the code is a simple if/else logic statement checking if our current menu has the .open
class. If we do have that class then the user clicked an open menu and we need to remove the class and close the menu. Otherwise it doesn’t have the class and we need to apply it onto the dropdown container, then have the menu animate a jQuery .slideDown() method.
Live Demo – Download Source Code
Final Thoughts
This is the perfect tutorial for newer web developers who are still just getting their feet wet. Basic HTML5/CSS3 code is easy to work with, but often overlooked as something simplistic and boring. However I would argue that most talented frontend web developers take HTML/CSS/JS practice very seriously.
Feel free to download a copy of my source code and play around on your own. There is a lot you can learn from this basic script, and it is also very easy to replicate on your own. If you have any similar ideas or questions feel free to share with us in the comments discussion area.