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 <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). (Actually, I’ve had a rethink about this option and there’s another example presented below.)

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:

Tags: , , , ,

Share this article:
  • Twitter
  • FriendFeed
  • del.icio.us
  • Digg
  • StumbleUpon
  • Facebook
  • Reddit
  • Sphinn

Subscribe to this site for regular updates

39 responses to Centering a dropdown menu. Add your own.

Comments

  1. 1

    Wouldn’t it be possible to just give the ul display:block and a width in your choice of unit, then apply margin:auto to 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.

  2. 2

    Actually, you’re quite right, Mike. I was over-thinking things. I’ve had a rethink and amended the article.

  3. 3

    I’ve been looking for something like this for ages. Thank you!

  4. 4

    Is it possible to have the second lvl items also horizontal?

  5. 5

    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)

  6. 6

    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:)

  7. 7

    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.

  8. 8

    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.

  9. 9

    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.

  10. 10

    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.

  11. 11

    This site is excellent

  12. 12

    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!

  13. 13

    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.

  14. 14

    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

  15. 15

    Hi Al,

    The original Sons of Suckerfish article includes a 3-level example.

  16. 16

    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 :)

  17. 17

    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.

  18. 18

    Thank you very match, your post is the most usefull that I have find. thank you John!!

  19. 19

    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

  20. 20

    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).

  21. 21

    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.

  22. 22

    Hi

    Been a while since I was last here but from what I have learned, the wrapping is a specific problem with the Gecko engine used by Firefox, apparently it doesn’t wait for all the components to be received before it attempts to layout the page. This causes the problem with the menu.

    I will try the additional tutorial listed first after pingbacks but another forum in Joomla suggested that forced refresh after the menu loads may sort out the problem in Firefox.

    M.

  23. 23

    Thanks for this wonderful guide. much appreciated. BUT I want to have 4 menu buttons in 4 different bgcolor ..(example: http://michau.superhit.in/menu/index.html ) with their respective sibmings in the same color: e.g. 1st menu item in RED and with its siblings in red, 2nd one in GREEN and siblings in green, 3rd one in black and black siblings and 4th one in yellow and yellow siblings. the parent level menu will be of fixed width. 2nd levels may differ.. allowing line breaks/auto wrapping etc.

    Thank you

  24. 24

    Genious!

    Finally solved this f***ed up problem.
    Thx so much for all your help… keep up this brillant work.

    jay

  25. 25

    Would just like to say this is ABSOLUTELY AMAZING!!! I’m so happy that we can make centered suckerfish dropdowns easily in the future. Thank you so much for your hard work! Thank you, thank you, thank you! ^_^

  26. 26

    hi John!
    This post is very most useful! I have a problem that you give the last sample in the post.
    Why diy you need to applied to behave float:left within #nav? it works fine in Firefox 3.5 and IE 7.
    if i remove it(float:left), It doesn’t work in Firefox 3.5.
    I’d be very thankful if you answer to this question!

  27. 27

    Allan, the float is required to contain the floated elements within it so that the background extends the full width of the available area. I usually use overflow:hidden to contain floats but can’t do that in this case because hiding the overflow would prevent the submenus from showing.

  28. 28

    What if you don’t know the total number of items in the menu?

  29. 29

    Hi Mark, if you don’t know the number of items you can use the table display method which doesn’t require setting a width on the parent, but you’d need to consider what would happen if too many items were added to fit the space, i.e, would they wrap or stick out or be hidden.

  30. 30

    I’ll give it a go but I also figured a different method. Since the only time I won’t know the number of items is on a dynamic menu, I can use the script to count the number of items and add a specific width to the unordered list.

  31. 31

    Sounds like a good idea.

  32. 32

    This is wonderful. Thank you!!

    Karen

  33. 33

    Hi, thanks, this article is a great help and saved me many hours of work. Just a display: table; for the ul did the job for me.

  34. 34

    One addition, to make the conditional comment with display: inline-block and so on work in ie the element within the <li> tags must be display: block, else the whole navigation floats left.

Pingbacks

  1. 1

    […] Centering a dropdown menu Last update: 2007-03-24 […]

  2. 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. 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 […]

  4. 4

    […] To have a dropdown for your own team copy over all of the content below. It might be needed to adjust a thing or two. Comments have been added throughout the code what must be changed. Inspirational websites: Most basic dropdown menu, with no submenu’s The javascript library used to add effects and optimise the dropdown How to center a ul list effectively […]

  5. 5

    […]Centering a Dropdown Menu with inline-block and table display[…]

Feed for this post's comments


Required indicates required field.
Email will not be published

You can use these tags in your reply:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Leave a Reply

Contact details