Build a User Settings Dropdown Menu with jQuery

by Jake Rocheleau

on July 26, 2012

in Tutorials

There are many social networking websites designed with a specific layout in mind. User profile pages are some of the more complex designs included with a community-based network. You’ll often have access to edit user profile settings, subscriptions, and e-mail options. I want to create such a simple menu for a minimalist Digg-style layout.

In this tutorial I have actually built two working demo pages. The first runs on jQuery to fade the menu in and out as you hover. The 2nd demo is built using just CSS effects which display the submenu using the :hover selector. It’s even easier to combine both methods for legacy support – however at that point I’d recommend the CSS-only methodology. But you can see for yourself in the live demo examples and build this yourself by following my code below.

jQuery sub-menu navigation dropdown

Building the Page Layout

Let’s start out by examining the default HTML5/CSS3 website structure. I’ve created a basic HTML5 doctype while including an external stl.css stylesheet and the latest version of jQuery 1.7.2.

<!doctype html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>User Profile Dropdown Menu - CSS+JS Demo</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="stylesheet" type="text/css" media="all" href="stl.css">
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
</head>

This is all pretty standard-looking, along with the rest of the page. Probably the most interesting markup is inside our <header> element which contains the unordered list of navigation links. For the dropdown menu I’ve embedded a sub-list inside a list item, which we hide using CSS.

<header>
	<h1 class="logo">CSS3+jQuery</h1>
	
	<ul class="profilenav">
		<li><a href="#">View Profile</a></li>
		<li><a href="#">Add Friends</a></li>
		<li id="settingslink"><a href="#" >My Settings</a>
		<div id="settingslist">
			<ul class="sub">
				<li><a href="#notifications">Notifications</a></li>
				<li><a href="#changePhoto">Change Photo</a></li>
				<li><a href="#editProfile">Edit Profile Info</a></li>
				<li><a href="#invite">Invite Friends</a></li>
				<li><a href="#connect">Connect an Account</a></li>
			</ul>
		</div>
		</li>
		<li><a href="#">Logout</a></li>
	</ul>
</header>

The container list item I’ve given the ID settingslink. This way we can easily target the element using jQuery. I have also setup the sub-menu inside a div using the ID settingslist. This seems easier than managing the entire unordered list since now we can apply background styles – drop shadows, text effects, and positioning – to this container element.

Basic Page Resets

I’m looking at my new stylesheet file which contains a myriad of important properties. At the very top you’ll find all the typical element selectors and default resets. Padding, margins, line-height, and font sizes are all reset so they’re uniform within every browser.

* { margin: 0; padding: 0; } 
body { background: #f0f6fa url('img/bg.png'); font-size: 62.5%; color: #343434; font-family: Corbel, "Lucida Grade", "Bitstream Vera Sans", "Luxi Serif", Verdana, Arial, sans-serif; }

ul { list-style: none; }

img { border: 0; }

a { color: #7496ce; }
a:hover { color: #89afee; }

h1 { font-size: 2.223em; color: #656565; font-weight: normal; letter-spacing: -0.05em; margin-bottom: 5px; }
h2 { font-size: 2.2em; font-family: Georgia, Times New Roman, serif; font-weight: normal; font-style: italic; letter-spacing: -0.08em; color: #839874; padding-top: 25px; }
h3 { font-size: 1.8em; font-weight: bold; text-decoration: underline; line-height: 2.4em; margin-bottom: 6px; }

p { font-size: 1.3em; line-height: 1.25em; color: #666; margin-bottom: 15px; }

The header element is actually setup as a container block piece. I’m using CSS3 gradients to color the glossy BG effect, with a typical fallback using solid colors. We’re also applying other CSS3 properties for a box shadow and rounded border radius effect.

#settingslink { position: relative; }
#settingslink a.hvr { background: #fff; color: #3f6998; }

header { 
display: block;
position: relative;
height: 55px;
border: 0;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
-moz-border-radius-bottomleft: 5px;
-moz-border-radius-bottomright: 5px;
-webkit-border-bottom-left-radius: 5px;
-webkit-border-bottom-right-radius: 5px;
background: #7499bf;
background: -moz-linear-gradient(top,  #7499bf 0%, #4579ac 50%, #255f97 51%, #2969a2 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7499bf), color-stop(50%,#4579ac), color-stop(51%,#255f97), color-stop(100%,#2969a2));
background: -webkit-linear-gradient(top,  #7499bf 0%,#4579ac 50%,#255f97 51%,#2969a2 100%);
background: -o-linear-gradient(top,  #7499bf 0%,#4579ac 50%,#255f97 51%,#2969a2 100%);
background: -ms-linear-gradient(top,  #7499bf 0%,#4579ac 50%,#255f97 51%,#2969a2 100%);
background: linear-gradient(to bottom,  #7499bf 0%,#4579ac 50%,#255f97 51%,#2969a2 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7499bf', endColorstr='#2969a2',GradientType=0 );
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.40);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,0.40);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.40);
}

Styling the Navigation

The only other key piece to our stylesheet involves the dropdown navigation links. For the sub-menu I’ve added display: none; so that nothing will show up on the page. This makes our job simpler with the jQuery fading methods.

The entire #settingslist div block acts as a container for the navigation menu. I’ve created a small drop shadow so that we see a 3-D effect on the flyout. But I have tried to not overuse the box shadows in this header area – although I feel the dropdown box can definitely benefit from some added texture.

.profilenav { position: absolute; right: 20px; }
.profilenav li { display: block; font-size: 1.2em; float: left;  }

.profilenav a { display: block; line-height: 55px; color: #b6cadd; font-weight: bold; text-decoration: none; padding: 0 10px; }
.profilenav a:hover { color: #fff; }

#settingslist { background: #fff; display: none; position: absolute; padding-top: 7px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.5); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); }
#settingslist .sub { background: #fff;  }
#settingslist .sub li { font-size: 1.0em; font-weight: bold; background: #fff; }
#settingslist .sub li a { display: block; line-height: 2.3em; padding: 3px 6px; color: #596774; width: 150px; }
#settingslist .sub li a:hover { background: #537db9; color: #fff; }

Everything else is typical floats and body effects for the page. We can now go back into index.html and create a new script tag right before the closing </body>. Here we can write some basic jQuery code to handle the dropdown menu effects.

Fading Menu with JavaScript

We can build this effect with a single block of code dialect. After the $(document).ready() clause I’ve created two variables – sub targets the sub-menu container and root targets the whole list item container. When you hover over the list item the submenu will fade in while also appending the .hvr class onto the containing link.

<script type="text/javascript">
    $(document).ready(function(){
	var sub = $("#settingslist");
	var root = $("#settingslink");
		
	$(root).hover(
	    function() {
	    sub.fadeIn("slow");
	    $("#settingslink a").addClass("hvr");
	    return false;
	},
	    function() {
	    sub.fadeOut("fast");
	    $("#settingslink a").removeClass("hvr");
	    return false;
	});
    });
</script>

I’m using the jQuery .hover() method because we can setup 2 distinct functions for hover on/off. The latest jQuery docs recommend using the .on() event handler in these situations. However there is an odd bug where the sub-menu will continually fade in-and-out as you move down the links.

After adding the link class I’m also using return false; for both effects. This will squash any bugs in your webpages if two different scripts clash. But ultimately this single block of code is heavily supported and should work for all modern standards-compliant browsers, as well as most smartphone browsers like Mobile Firefox, Chrome, and Safari.

CSS-Only Approach

In the demo folder I’ve separated two versions of this webapp for CSS/JS and CSS-only. I want to jump over now to looking at the CSS-only approach. I’ve removed the whole script block and the external jQuery library from the index.html head. All the other classes and IDs should be fine to work with.

The changes are all inside our stylesheet where I’ve created new hover rules for the #settingslist element. By default we still use display: none; and only update this when hovering over the list item block.

#settingslink { position: relative; }
#settingslink:hover { background: #fff !important; }
#settingslink:hover a { color: #3f6998; }

.profilenav { position: absolute; right: 20px; }
.profilenav li { display: block; font-size: 1.2em; float: left;  }

.profilenav a { display: block; line-height: 55px; color: #b6cadd; font-weight: bold; text-decoration: none; padding: 0 10px; }
.profilenav a:hover { color: #fff; }

.profilenav li:hover #settingslist { display: block; position: absolute; }

#settingslist { background: #fff; display: none; position: absolute; padding-top: 7px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); -moz-box-shadow: 0 1px 1px rgba(0,0,0,0.5); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); }
#settingslist .sub { background: #fff;  }
#settingslist .sub li { font-size: 1.0em; font-weight: bold; background: #fff; }
#settingslist .sub li a { display: block; line-height: 2.3em; padding: 3px 6px; color: #596774; width: 150px; }
#settingslist .sub li a:hover { background: #537db9; color: #fff; }

The syntax looks slightly outlandish at first, but you’ll realize this is a much simpler way of defining dropdown menus. The selector code .profilenav li:hover #settingslist doesn’t need to use an ID element. But it just so happens our container div could be most easily targeted this way, and the list item is an overall container for the sub-menu.

jQuery sub-menu navigation dropdown

Final Thoughts

This tutorial is meant to guide you towards learning a couple solutions for creating a dropdown menu with HTML5/CSS3 on the frontend. The code examples are minimalist in the hopes that you’ll adapt this code to work in your own websites. And support for even mobile browsers can lead to increased traffic stats.

I truly love the effects you can pull off with jQuery – but admittedly CSS can perform on its own just as well. Feel free to download my demo source code and check out how this whole dropdown menu works. Similarly if you have questions or ideas on the tutorial feel free to share with us in the post discussion area below.

Powered by Shutterstock

About Jake Rocheleau

Jake is a digital researcher and writer on many popular design magazines. He frequently writes on topics including web design, user experience, mobile apps, and project management. You can find him all throughout Google and tweeting @jakerocheleau. Connect with Jake on google+