I have been loving the redesign of whitehouse.gov that coincided with Obama’s inauguration since, well, his inauguration. One of the things that impressed me the most is its navigational menu. It is a horizontal, pull-down style menu, but what is most interesting to me is the “mega” nature of the sub-menus.
It so happens that I was in the midst of designing a new website for the organization I work for, Alliance for a Just Society, formerly Northwest Federations of Community Organizations. As part of the process, one of the first steps I wanted to take was to attempt a navigational menu inspired by whitehouse.gov.
Here is a demo, and below are some notes on how I got there.
According to this site, my beloved menu is created using the Superfish jQuery plugin.
I visited the Superfish site and downloaded the zip archive. From the archive’s contents, I used the following:
- example.html
- superfish.css
- jquery-1.4.x.min.js
- hoverIntent.js
- superfish.js
- arrows-ffffff.png
- shadow.png
First, I customized example.html a bit.
I ended up overriding superfish’s default options by specifying the following:
$(document).ready(function() {
$('ul.sf-menu').superfish({
delay: 500, // the delay in milliseconds that the mouse can remain outside a submenu without it closing
speed: 200, // speed of the animation. Equivalent to second parameter of jQuery's .animate() method
dropShadows: false, // completely disable drop shadows by setting this to false
});
});
I changed the text of the navigation menu and sub-menus. I wanted to be able to quickly determine parent/child relationships and menu depth. As an example…
Top Level Navigation: A, B, C, etc…
2nd level navigation: A1, A2, A3, etc…
3rd level navigation: A1 A, A1 B, A1 C, etc…
The bulk of the customization happened in the style sheet, superfish.css.
First, I wanted my sub-menus to appear properly “mega.” That is, I wanted the width of the sub-menus to be generously oversized. To do so, I simply ensured that
.sf-menu ul { width: 20em; }
If I were to keep 3rd and 4th level menus, I would want to make sure that the 20em width was reflected in the appropriate classes.
ul.sf-menu li li:hover ul,
ul.sf-menu li li.sfHover ul { left: 20em; }
ul.sf-menu li li li:hover ul,
ul.sf-menu li li li.sfHover ul { left: 20em; }
The second thing I wanted to achieve was to ensure that 3rd and 4th level sub-menus are not visible. To do so, I commented out the following lines.
/* commenting this out, I don't want to see any ul 3 level items and deeper
ul.sf-menu li li:hover ul,
ul.sf-menu li li.sfHover ul {
left: 20em; /* match ul width
top: 0;
}
*/
/* commenting this out, it would apply to uls 4 levels deeper, but this is already inherited above
ul.sf-menu li li:hover li ul,
ul.sf-menu li li.sfHover li ul {
top: -999em;
}
ul.sf-menu li li li:hover ul,
ul.sf-menu li li li.sfHover ul {
left: 20em; /* match ul width
top: 0;
}
*/
Even though I hid the 3rd and 4th level menus, I was still left with the indicator arrow. To get rid of those unwanted arrows, I specified “background: none” in the following lines:
.sf-menu ul .sf-sub-indicator { background: none; }
.sf-menu ul a > .sf-sub-indicator { background: none; }
Next I wanted links in my sub-menu to appear as “columns.” To do so, I specified an approximate “halfway” width for the sub-menu’s list items.
.sf-menu li li { width: 45%; } /* places list items into "columns" */
After playing around with it, I wasn’t too happy with the way some of the longer list items clogged up the floated flow. The solution I found works wonderfully in Firefox, but alas not so well in Internet Explorer (surprised?). If anyone has a better solution, I would love to hear it.
.sf-menu li li:nth-child(odd) { clear: left; } /* this is important so that long items in 2nd level don't make floats weird looking, doesn't seem to work in IE */
The navigational menu still looks weird. I realized that much of this could be corrected through the use of colors, borders, etc…
I was feeling pretty good about the whole thing. But, while testing it all out, I realized that there was a large useability problem. When hovering over a main navigation item, a sub-menu normally appears below and to the right of it’s parent. What about if the parent was at the right-hand side of the screen?
Hover over “H” in example 7.
The folks behind whitehouse.gov solved this problem. The answer is that when a user hovers over a menu item that shows on the right half of the page, a sub-menu appears as normal, but pointed to the left, rather than to the right – as if each half of the navigational menu is a mirror image of the other half.
My implementation of whitehouse.gov’s solution is a little bit of a pain in the butt. If you have a suggestion for a better way, please do not hesitate to comment and share below! My solution was to ensure that top level menu items were assigned a unique id and assigned a specific width. Then that id was used in my CSS as follows:
/* for the right half of navigation; basically takes submenu and pushes it leftward, rather than rightward */
/* sucky thing is that need to specify id's */
#level-e ul,
#level-e:hover ul,
#level-e.sfhover ul,
#level-f ul,
#level-f:hover ul,
#level-f.sfhover ul,
#level-g ul,
#level-g:hover ul,
#level-g.sfhover ul,
#level-h ul,
#level-h:hover ul,
#level-h.sfhover ul {
left: -12em;
border: 0;
border-right: 1px solid #fff;
border-bottom: 3px solid #000;
}
and
.sf-menu > li { width: 10em; } /* this is necessary for implementing the right 1/2 of nav menu & it's submenu, otherwise don't know how much negative left positioning to apply */
Finally, I took the overall navigational menu and floated it left.
Was this exactly what you needed? Did this how-to suck? Did I leave something out? Do you have a better solution? Comment and share below!


27 Comments
Hey Dennis:
I’m doing something very similar, trying to add superfish drop-downs to a WP blog, and it just won’t show up. I saw your comment on ericmmartin.com’s article about using JQuery with WP and followed it here hoping you’d written about what you did to get it working, but alas, nothing. Any tips? I’ve followed Eric’s tips as far as I can understand them, but with no success. I also followed your ‘themocracy’ link but didn’t get much out of it. I’d be delighted if you had some tips…
Hi Mandel:
Thanks for commenting & asking a question. I sometimes wonder if anyone reads this blog, or if I’m just doing it for my own future reference. I hope the info below is helpful.
1) The key thing that was pointed out on ericmartin.com’s article is that you “enqueue” your javascript/jquery files.
Here’s what I have in my functions.php – it’s more than you need, but at least you can see my approach – also, make sure to look at the comments.
2) The relevant piece from the themocracy.com post is that you define the relative location of your theme files – this allows you to know that you’re “pointing” to the right place. I added this to my functions.php before the enqueue section above.
3. each of my customized javascript files has something like this at the top – here’s my nav.js – used not in the post above, but in a WordPress site I’m currently working on.
Also, the above post is based on a “proof of concept” type exercise I was doing. I wanted to see if I could pull off the navigation I wanted in the simplest way possible – using good, old plain html, css & javascript.
If so, the next step would be expanding the concept & trying to integrate it with WordPress, which I have since done, but have not posted anything about. Your question, Mandel, is inspiring me to write that post.
Thanks for getting back to me with such a comprehensive answer!
I’ve put the code into my functions.php page in the current theme, and it is generating links to both jquery and to the superfish.js file, but I still don’t get the drop-down. This does work on every regular page on the site, so I know that I have configured it correctly there; I assume this is a WordPress related conflict.
Two quick questions:
1. Did you customize superfish.js to add this:
jQuery(function ($) {/* You can safely use $ in this code block to reference jQuery */
});
in place of the ;function($){ which starts it off? If so, are you not meant to put all the code between the { brackets } ??
2. Do you use your custom js file instead of the standard block of script in the page itself? I was putting this in the header, but with no luck (and I did try wrapping it in the code block in my 1st question):
// initialise superfish
$(document).ready(function() {
$('ul.sf-menu').superfish({
autoArrows: false // disable generation of arrow mark-up
});
});
Sigh. This is one of those time-sucking things…
Actually, no – I didn’t alter superfish.js at all.
Oh, yes I created new javascript files. For the navigation, I titled it nav.js & referenced it in the enqueuing step:
// load nav.js -- the array ('jquery', 'hoverIntent', 'superfish') declares dependencies
wp_enqueue_script('nav', THEM_TEMPLATEURL.'/js/nav.js', array('jquery', 'hoverIntent', 'superfish'), '1.0', true);
Notice the version 1.0!
My first instinct was to put it in the header.php file, but after it didn’t work, I tried putting it as a separate .js file – and, thankfully, that did end up working.
I treated nav.js along the same “cascading” principle as CSS. My approach to javascript is very hack-y, I don’t really know it all that well.
I figured if you declare dependencies in the enqueing process, then maybe a “cascading” type principle, like CSS, would apply. First it would process jQuery. Then get supplemented by hoverIntent and Superfish. Finally, by my nav.js. If there was any conflict, then the newest in that stack would rule. Seems sound, right?
Well I have no idea if that “cascading” principle is correct or not, but the navigation ended up working.
Out of curiosity, do you have a URL I could look at where you trying this all out?
Thanks for the suggestions. I’ll try them and then get back to you with an URL if they don’t work. I do appreciate your time and thoughts on this!
This was just the thing at just the time — have been futzing around with a very similar thing and your left/right solution is elegant. (And, I saw your comment about visitors, so thought I’d let you know I was here. ;-) )
Thanks for commenting, visitor. I appreciate it. On the right/left thing, there’s probably a better way to achieve it, but thanks either way.
“When hovering over a main navigation item, a sub-menu normally appears below and to the right of it’s parent. What about if the parent was at the right-hand side of the screen?” I have been looking for a solution for this problem for days, and finally stumbled upon your solution, good work. I think you’re right, though, there’s probably a better / more efficient way to do it. If you do find a better solution, will you post here?
Hey Pete – yes, of course, I’ll post a better solution if I find it. And, thanks for the feedback. I’m currently working this into a custom WordPress theme. Luckily, WP assigns unique IDs to everything, including top-level menu items. This makes implementing this somewhat awkward solution easier.
I use a CMS that also assigns unique IDs to everything but doesn’t publish those ID’s on the frontend so it does make your solution difficult to implement using that CMS.
Not sure if you’ve already seen this…
http://users.tpg.com.au/j_birch/plugins/superfish/supposition-test/index.html
… but it looks like work on it has stalled since 2008.
No, I haven’t come across Supposition before. I wish I had played with it from the start. Thanks for sharing!
I think, there is no need to use Superfish and Superfish’s complex CSS for to create a menu like whitehouse.gov. It can be done easily with using couple of JQuery code and simple CSS. An that simple JQuery code can solve the align of right items problem itself. Tested on Opera, Firefox, Chrome and IE8. Check this out.
#main-menu, #main-menu * {
margin: 0;
padding: 0;
list-style-type: none;
font-family: Georgia;
}
#main-menu {
background-color: #185087;
width: 100%;
float: left;
font-size: 12px;
}
#main-menu li {
border: none;
display: block;
float: left;
}
#main-menu a {
color: #eee;
text-decoration: none;
padding: 7px 39px;
display: block;
font-weight: bold;
}
#main-menu li.hover a {
background-color: #fff;
color: #185087;
border-top: 3px solid #bd1e12;
padding-top: 4px;
}
#main-menu ul {
width: 500px;
display: none;
position: absolute;
z-index: 10;
border-bottom: 3px solid #bd1e12;
background-color: #fff;
padding: 5px 0;
}
#main-menu li.hover ul li {
width: 250px;
}
#main-menu li.hover ul a {
color: #185087;
border: none;
font-weight: normal;
text-decoration: none;
}
#main-menu li.hover ul a:hover {
text-decoration: underline;
}
BLOG
PHOTOS & VIDEOS
Photo Galleries
Live Streams
Video
Podcasts
BRIEFING ROOM
Photo Galleries
Live Streams
Video
Podcasts
$(document).ready(function(){
var menu_item_length = $('#main-menu>li').length;
$('#main-menu>li').each(function(i) {
if (i>(menu_item_length/2))
$(this).find('ul').css('margin-left', $(this).width()-$(this).find('ul').width());
});
$('#main-menu>li').hover(
function() {
$(this).addClass('hover');
$(this).find('ul').css('display', 'block');
},
function() {
$(this).removeClass('hover');
$(this).find('ul').css('display', 'none');
}
);
});
In your example you hid the 3rd and 4th level menus, but what if I want them to display as they do on whitehouse.gov (where the 2nd and 3rd level items appear in the same dropdown menu; the 2nd level items are bolded whereas the 3rd level items are not)?
Hi Kristen,
Adding the 3rd level menu item shouldn’t be so bad. It would all be specified in the style sheet.
– You would not comment anything out before line # 9 as shown after example 2 in the post.
– You would still apply “background: none;” as shown after example 3.
– You’d just make sure that any left padding or left margin applied on 3rd ul was in line with its parent ul.
– And you’d set the “font weight: bold” on the 2rd, but not the 3th ul.
Ahh just what I need. I’ve been looking for an easy tutorial on how to mimic whitehouse.gov’s top navigation menu.
After completing a website from a client project, they wanted more and saw whitehouse.gov. Oh well, clients are the lifeblood in business so I’m excited to try this out!
Will let you know and link your site to my site. Thanks for sharing Dposorio!
Thanks for the feedback Francis!
That’s a great article! I have bookmarked it for future reference. I’m playing around with Mojo Portal. It’s a .Net based CMS with support for superfish.
hi, good tutorial, Im updating the styling and look of my menu and this was helpful!
You might want to check out your site here:
http://nwfco.org/
There are some little things you might want to check into on the front page not quite right (Im on firefox).
Thanks
Hello,
This is what I’ve been searching for, thanks for all your effort and know that it is not in vain. Like yourself I have been trying to replicate the whitehouse design but stuck on a key area. I am wondering how to display my menu with the main logo separating the list at the middle. I had placed the logo in the unordered list so that it is centred in-between the first four links and the last 3 links (4 and 3 links on each side of it). The logo will extend beyond the background of the “navigation div”.
The first picture is the ideal requirement while the second picture is what I get when I used the code below. How can I get the list to stop at “BUSINESS” and then continue after the logo with “VIDEOS, PRESS RELEASES and EVENTS”. Thanks for your help.
Hi Tony — your code didn’t come out too well within the comment field or something. Is there something you can link to that I can have a look at? Also, I’m glad you found this post and that it was helpful! — Dennis
Thanks a lot for getting back to me Dennis. I have worked on this but still unsuccessful in getting the logo to sit comfortably at the middle with the menu items on both sides (“HOME, BIO, POLITICS, BUSINESS, LOGO, PRESS RELEASES, VIDEOS, CONTACT”). Have a look at the code and the test site link below: http://www.riverdrill.com/services.html
Hi Tony,
It looks like you have a few problems with the menu that should be addressed before you position the logo.
On line #105 of services.html, I don’t think that you really want
ul#topnavto haveposition: fixed;— I suspect it should beposition: relative;instead.Also, I would make sure your html validates before investing much time in getting this to work. http://validator.w3.org/.
Finally, you can’t move the logo around without having to move the entire page background along with it. That means you have to position the menu
ul#topnavinstead.http://tonyep.webcltd.com/header01e.jpg
Good luck!
I am not able to open any of the example links above. Page Not Found Error.
Is there any other link to see the final code OR would it be possible to send me the example to be email account given above.
Broken links have now been fixed! Thanks, Rajeev, for bringing that to my attention.
I’m trying to replicate this on a wordpress site…not that great in Js but I can’t get it to work correctly I was wondering if you could take a look at it as I want to be able to call on WP custom nav if/when it changes.
Sure thing. You should reply and include a URL. I’m happy to take a look & see if anything jumps out at me.