Centering a dropdown menu
Recently, I needed to create a centered version of the Suckerfish dropdown menu and realised that some significant modifications were going to be needed. This is because the method for getting the top level list items to sit in a row, on the same horizontal plane, is to use float: left. However, when you float elements, you can’t centre them unless you give them a width and use auto left and right margins.
If you can give each list item a fixed width and then calculate the overall width of all the list items, you could give the (Actually, I’ve had a rethink about this option and there’s another example presented below.)<ul> a width and centre it, but this isn’t always a viable solution (e.g. the number of items may change or text size changes become a consideration).
The menu’s on the table
What I went with made use of a property of CSS that isn’t utilised much due to it being unsupported by Internet Explorer. The significant changes are below.
#nav {
background-color: #F00;
text-align: center
}
#nav ul {
display: table;
margin: 0 auto;
}
#nav li {
display: table-cell;
position: relative;
width: 11em
}
#nav li li { display: block }
So what’s this display: table and display: table-cell about? Well, as the names suggest, using these properties makes the elements they’re applied to behave like tables.
So for #nav li, display: table-cell means that not only will the list items shrinkwrap to fit their content, but they’ll also appear on the same line, as cells in a table would. The display: table on #nav ul means that the <ul> is then only as wide as the contents of all the cells it contains (instead of being 100% of the available space) and it is able to be centered using text-align: center on the parent container.
Not on IE’s table
As mentioned before, IE (including version 7) doesn’t support display: table, so the above code is only going to work in non-IE browsers. So, just for IE, we need to introduce another of the display properties:
#nav ul { display: inline-block }
#nav li { display: inline }
#nav a { display: inline-block }
#nav li:hover ul { top: 1.3em; left: 0 }
An inline block is one that is placed inline, on the same line as adjacent content, but behaves like a block. With IE, this only works for elements that are already inline, so what’s actually going on here is best described by Bruno Fassino:
The first line gives hasLayout. The second one resets the display as desired, without taking back hasLayout…
…Elements having both hasLayout and display:inline work similarly to the standard inline-blocks: they flow horizontally like words in a paragraph, are sensitive to vertical-align, and apply a sort of shrink-wrapping to their contents (which can include block elements.)
As mentioned, IE understands display: inline-block when applied to inline elements which is where #nav a { display: inline-block } comes in. The #nav li:hover ul { top: 1.3em; left: 0 } is required to move the dropdown menus below the parent list item (otherwise they appear over the top). Likewise, left: 0 is needed rather than left: auto because IE gets the positioning of the dropdowns wrong.
These extra rules are required for all Windows versions of IE which means conditional comments are really the only viable option in this instance. The completed example, which works in Firefox, IE6 & 7, Opera 8.5 & 9, Mozilla, Netscape, Safari and Konqueror, shows how all this is put together including the conditional comments and the other pieces of the CSS that I’ve missed so far.
(In case you’re wondering, I’m using the whatever:hover instead of the original Suckerfish article javascript to get IE6 to accept :hover on the list items.)
Everyone eating at the same table
Having completed this example I began to think about whether it would be possible to do the same thing but without the need for different code for Internet Explorer. What I came up with used the more familiar display: inline:
#nav li {
display: inline;
position: relative;
width: 11em
}
#nav a {
width: 6em;
padding: 0 2.5em;
line-height: 1.6;
color: #FFF;
background-color: #F00
}
#nav li li, #nav li li a { display: block; height: 1.5em }
#nav li li a { width: auto; padding: 0 }
#nav li:hover ul { top: 1.5em; left: 0 }
I won’t go into too much detail about the workings of this example because, while it works fine in Firefox and IE6 & 7, it fails rather badly in Opera 8.5 & 9 (it’s actually better in 8.5) on Windows which seems due to a bug in Opera which affects absolutely positioned (the dropdowns) elements inside inline (the top level list items) and is similar to a problem I had with image replacement and buttons. The solution there was to float the inline element but, of course, to do that means that the menu is no longer centred.
It also doesn’t look quite right in Mac browsers but as it doesn’t really have any practical, real world use due to its Opera limitations, I haven’t investigated ways to correct this. Of course, if anyone has any thoughts on how to make it work better cross browser, I’d love to hear them.
A slight rethink
The main advantage of using the display: table method is that you don’t need to set a width on any of the elements which means that you can set a bit of margin or padding on the top level list items and you could then add and remove list items (within reason) without having to change any of your CSS.
But, of course, for the effect that I’ve been trying to achieve with these examples, I’ve had to set a width so that the top level list items and their dropdown submenus are the same width. So, as Mike Cherim points out in the comments, there’s really no reason not to set a width on the <ul> and just centre it with margin: 0 auto.
#nav {
float: left;
width: 100%;
background-color: #F00;
text-align: center
}
#nav ul {
width: 44.1em;
margin: 0 auto;
list-style: none;
}
#nav li {
float: left;
position: relative;
width: 11em
}
All we need to do is give the <ul> a width equal to the combined total of the list items (a fraction more needed to prevent IE6 & 7 turning the last item to a new line) and then margin: 0 auto. This works fine in the IEs, but in other browsers, it means the red bar doesn’t extend the full width of the page anymore. Using overflow: hidden is my usual fix for getting non-IE browsers to contain the floats, but in this case hiding the overflow hides the dropdown menus, so instead I’ve floated #nav and given it a width of 100% (as floats will expand to contain other floats).
This example is actually the simplest, and most straightforward approach of them all and doesn’t require the use of any conditional comments (if you don’t count the one needed to give IE6 :hover behaviour on the list items).
So, it turns out I probably could’ve made things much easier on myself from the start. But I still think it’s useful to not only consider that there are often many different ways to approach different techniques with CSS, but also to realise that cross browser limitations (and that’s not always confined to IE) mean that some techniques can’t always be used.
Browse by tags:
Subscribe to this site for regular updates
24 responses to Centering a dropdown menu. Add your own.
Comments
Pingbacks
-
1
[...] Centering a dropdown menu Last update: 2007-03-24 [...]
-
2
[...] Centering a dropdown menu — Tyssen Design … hiding the overflow hides the dropdown menus, so instead I’ve floated #nav and … CSS Example Menu 4: Centered Menu :: Dynamic Site Solutions | A… http://www.tyssendesign.com.au/articles/css/centering-a-dropdown-menu/ [...]
-
3
[...] menu so after much fighting with the code, I created a suckerfish style one with this tutorial: http://www.tyssendesign.com.au/articles/cs…-dropdown-menu/It works perfect in FF (mac & pc) Safari, IE7 but not IE6. I'm not sure what I've done [...]














Wouldn’t it be possible to just give the
uldisplay:blockand a width in your choice of unit, then applymargin:autoto the thing? This is what I do if I want to center a horizontal nav list, instead of floating it. Admittedly I don’t really know the Suckerfish system — it appears to be just nested unordered lists though so I’m just curious.Actually, you’re quite right, Mike. I was over-thinking things. I’ve had a rethink and amended the article.
I’ve been looking for something like this for ages. Thank you!
Is it possible to have the second lvl items also horizontal?
I’m having a lot of trouble with these CSS drop down menus. I want the initial items in the menu to have padding on the right and left of the text, rather than have a fixed width. This is because I am required to put a lot of items in my initial menu. No matter what I do (block floated, inline, etc), there are problems with hovers, or widths, in both major browsers. I need help as I dont want to have to use a javascript method (runs too slow, bad for seo)
I have only one question that I can’t find the answer for it for a long time.
Imagine i have 2 frames - upper and lower. The upper frame contains a drop-down menu. How can i prevent my menu from hiding under the second frame when it drops down?
I’d be very thankful if you answer to this question:)
Hi Ani,
I don’t believe it’s possible to have dropdown menus appear outside the frame they’re contained within. Your best approach may be to lose the frames - there’s very little reason to use them anymore these days and if you’re using them just so you have a single file that controls your menu across all pages, then you should look into using server side includes instead.
Hi, I have bug problem with table display and firefox 2.0.0.6
My menu doesn’t work at each time …
And when it fails, in doing “F5″ it was good.
That’s very strange. I have the problem on opera and FF.
It was probably because of “left: -999em;” code in #nav li ul.
Hi Crash,
I’d really need to see a link to your page or your code to be able to offer any suggestions, but as this isn’t really the best place for posting code and troubleshooting problems, I’d suggest posting your question to Sitepoint or CSSCreator.
So, close yet so far :p This is exactly what I was looking for, except that the menu I have is dynamic - it changes depending on certain factors. That means I can’t tell what the width will be. Been trying to look for a solution for the past few days but haven’t found anything yet.
This site is excellent
Hi,
Is it possible to center the Suckertree drop down menu in a table?? If so, I would really appreciate knowing what the simple css code is that I’d need to add to do it? The above suggestion doesn’t work in my table. Thanks!
Hi Anne,
Using the methods described above, it shouldn’t matter what element the menu is contained within. If it doesn’t work in your situation, you’d need to provide your code or a link to troubleshoot the problem. But you’d be better posting your question to a forum like CSS Creator.
Ok Wow this is great information.
Thank you
I have been trying like crazy to center the son of sucker fish. I’m a novice and barely understand what is going on here
One question how would I create a third level to pop out (sub level 1.1.1) for example?
Like button “Demos”
http://www.cssplay.co.uk/menus/final_drop.html
Thank you kindly,
Al
Hi Al,
The original Sons of Suckerfish article includes a 3-level example.
Hi John
Thank you for the response.
I’ll just integrate the 3rd level code fm. the orig son of sucker fish into your centered navigation code?
I can do this. I just want to make sure I’m working on something that will work after I spend 10 hrs figuring it out
The centering only really deals with the positioning of the top level list items and doesn’t really affect the submenus, so yes, it should work fine; you’ll just need to play around with your top and left values to get it right.
Thank you very match, your post is the most usefull that I have find. thank you John!!
Hi
I’ve tried implementing your solution within Joomla but have run into a problem that I just can’t figure out.
Everything works as expected on my WAMP Server 2 based dev box for IE6 & 7, FF2, Opera 9+ and Safari for windows.
When I upload FF starts randomly wrapping the menu; no specific menu choice, no specific number of selections.
I’m hoping you can help or it’s back to the drawing board with 10 days to launch :o(
Thanks
M
Hi Michael,
I’ve just checked out the page in Firefox 2 & 3 and the menu seems to work fine (at least the same as it does in Opera and Safari).
Hi John
Thanks for taking a look.
You may need to play a bit, try quick succession of menu choices with intermittent refreshes.
The thing just wraps and it’s not even the same break as it can happen at different points in the menu.
I’ve been trying to figure it out for over a week now with no success.
Thanks
M.