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.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Alpha
  • 7,586
  • 8
  • 59
  • 92
  • 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 =( – David Thomas Jul 30 '09 at 01:12
  • 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 – Alpha Jul 30 '09 at 13:40

6 Answers6

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.

JeanValjean
  • 17,172
  • 23
  • 113
  • 157
  • 1
    I don't quite understand the 1% being required; can you elaborate on it? – Petrogad Sep 04 '12 at 17:53
  • 3
    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. – JeanValjean Sep 05 '12 at 07:45
  • Awesome. After reading fifty posts saying to to kluge it with a pseudo-element, I still knew there had to be a proper way. – Adam Mackler Mar 29 '14 at 23:48
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;
Darryl Hein
  • 142,451
  • 95
  • 218
  • 261
  • thank you jesse, you made my day by pointing out this property to me – cardflopper Oct 17 '09 at 00:07
  • 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+ – Austin S. May 14 '12 at 12:36
  • could you please specify which element should have this style? the li? the ul? the div? thank you. – Clinton J Oct 14 '14 at 20:33
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.

mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • 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. – Alpha Jul 30 '09 at 13:45
  • 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');` – Richard Christensen Feb 13 '14 at 21:21
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.

Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
  • 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 =/ – David Thomas Jul 30 '09 at 01:17
  • 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. – Ballsacian1 Jul 30 '09 at 01:20
  • 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! – Alpha Jul 30 '09 at 13:47
  • I recommend setting the padding on the link inside the li (if it's a menu) since it increases the clickable area. – Jonas Stensved Aug 16 '11 at 06:46
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.

L84
  • 45,514
  • 58
  • 177
  • 257
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;
}
Glenn Dayton
  • 1,410
  • 2
  • 20
  • 38
Mark
  • 1,455
  • 3
  • 28
  • 51
  • Thanks for the responso, but I see you are manually setting the width of the li elements, which is what I needed to avoid. – Alpha Dec 10 '11 at 16:05