CSS horizontal menu - equally spaced?
Asked Answered
C

6

12

I have a standard CSS menu, made with UL and LI tags. I need them to get to cover the whole page, horizontally (not my real case, but I'll take this to simplify the situation). However, the items are created dynamically and so I'm not able to hardcode any with to LI items, nor margins.

I've seen solutions using JavaScript to set those values but I would really love to avoid them.

Lastly, I've seen a pretty good solution which is setting

#menu {
    width: 100%;
    /* etc */
}
#menu ul {
    display: table;
}
#menu ul li {
    display: table-cell;
}

This will create the desired behavior in most browsers... except for IE.

Any ideas?

EDIT: Thanks for the responses. However, as the code that generates the items isn't mine, I'm not able to set inline styles when creating them without using JavaScript later.

Calliecalligraphy answered 30/7, 2009 at 0:59 Comment(2)
You need them to "cover the whole page"? Do you mean horizontally 100% page width, divided equally? Would you be able to have standard buttons across each page, with dynamically-created sub-menus? Also: which version of IE is giving the problem? I assume it's the display: table /* or table-cell */ that's causing problems. Despite my inner-distaste, you may be as well off using real html tables, if you're rendering that way...I'm sorry =(Urology
Hi. It is not necessary to cover the whole page, but I made it that way to simplify the situation. And yes, they should be spaced equally. I did not understand very well the button question. Are you referring to the standard <button> element? I tried it with IE 6, IE 7 and haven't tried with IE 8 yet. Also, my first approach was using tables as I couldn't get desired results on other way... but this comes up from a template generator so I'm bound to lists. Thanks anyway. =)Calliecalligraphy
R
14

You can't set the height or width of an inline element. http://www.w3.org/TR/CSS2/visudet.html#inline-width

Try display:inline-block;

here is the fix for ie:

display:inline-block;
zoom:1;
*display:inline;
Reposeful answered 8/9, 2009 at 18:43 Comment(3)
thank you jesse, you made my day by pointing out this property to meErr
Alpha, this should be flagged as the CORRECT answer for posted question. This is the most accurate and comprehensive way to have inline block elements properly on most browsers including IE6+Alansen
could you please specify which element should have this style? the li? the ul? the div? thank you.Lynxeyed
C
14

If you want to let the element get the whole available space, there is no need to define a priori the width of the menu elements (of course, it will help in equally sizing the li elements). You can solve this problem by working on the display property.

#menu{
  display: table;
  width: 100%;
}

#menu > ul {
  display: table-row;
  width: 100%;
}

#menu > ul >li {
  display: table-cell;
  width:1%
}

Note that width:1% is required to avoid cell collapsing.

Chaparral answered 23/8, 2012 at 17:5 Comment(3)
I don't quite understand the 1% being required; can you elaborate on it?Buccal
It is a little trick (and also a common practice)! I know it seems to make no sense, but it should set the width of something to be the minimum necessary to fit the content. In fact, even if you set the width to 1%, if the content is 200px wide, it will be shown at minimium 200px. Someone also add the "white-space:nowrap" property, but it is necessary depending on the case. Regards.Chaparral
Awesome. After reading fifty posts saying to to kluge it with a pseudo-element, I still knew there had to be a proper way.Darksome
T
4

If your menu items are being dynamically generated (so you don't know how many there will be prior) then you can add a style="width:xx" attribute to the lis (or in <style> at the top... or where ever you please, really). Where xx should either by width_of_parent_div_in_px/number_of_elements+'px', or 100/number_of_elements+'%'. The lis should also be block-level elements, and floated left.

Teilo answered 30/7, 2009 at 1:10 Comment(2)
Thanks, it seems like a clean solution, however, the code that generates items is not mine and I would not be able to set the style without using javascript. Sorry for not mentioning that before.Calliecalligraphy
Stumbbled in here 4 years later. Since you are using Javascript and these days JQuery you could do: var listId = $('#listId'); var listItems = listId.children('li'); var listItemCount = listItems.length; listItems.css('width',listId.width/listItemCount + 'px');Condign
V
1
#menu ul li {
    float: left;
    clear: none;
    display: inline;
    padding: 10px;
    height: 25px; //how tall you want them to be
    width: 18%; //you will need to set the width so that all the li's can fit on the same line.
}

The width: 18% may be about right if you have 5 elements across, accounting for border and padding. But it will vary due to how many elements you have, how much padding, etc.

Vale answered 30/7, 2009 at 1:4 Comment(4)
You know, I'm not convinced that what he said is what he meant, regarding the 'fill the whole page' (height: 100%). I assume -and I could definitely be wrong- that he meant only horizontally. Filling the whole page with navigation just sounds wrong =/Urology
the height: 100% is referring to the li tag and that the ul. Presumably he has the ul already set to a specific height, or has another wrapping element with a specific height. The height: 100% would just ensure that it is taking up all available space.Astray
That's right, when referring to "filling the whole page" I meant horizontally, sorry for not making it clear before. Already edited the question. Thanks!Calliecalligraphy
I recommend setting the padding on the link inside the li (if it's a menu) since it increases the clickable area.Trilemma
E
1

If you are open to using Flexbox then it isn't hard to do. Full credit for the code I am about to post goes to CSS Tricks as this is their CSS.

Below is an example that includes vendor prefixes.

#menu{
  
  list-style: none;
  
  -ms-box-orient: horizontal;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -moz-flex;
  display: -webkit-flex;
  display: flex;
  -webkit-justify-content: space-around; 
  justify-content: space-around; 
  
 }
<ul id="menu">
  <li>Home</li>
  <li>Store</li>
  <li>Blog</li>
  <li>About</li>
  <li>Contact</li>
</ul>

The only issue with Flexbox is if you need to support IE 9 and below, otherwise, I see no reason to not use Flexbox. You can view browser support for Flexbox here.

Epagoge answered 1/7, 2015 at 3:53 Comment(0)
D
0

Here's what worked for me:

#menu{
    height:31px;
    width:930px;
    margin:0 auto;
    padding:3px 0px 0px 90px;
    color:#FFF;
    font-size:11px;
}
#menu ul{
    display:inline;
    width:930px;
    margin: 0 auto;
}
#menu ul li{
    list-style:none;
    padding:0px 0px 0px 0px;
    display:inline;
    float:left;
    width:155px;
}
Darien answered 5/12, 2011 at 18:16 Comment(1)
Thanks for the responso, but I see you are manually setting the width of the li elements, which is what I needed to avoid.Calliecalligraphy

© 2022 - 2024 — McMap. All rights reserved.