tags:

views:

92

answers:

3

hey,

How do I make nested li's the same width?

When I use the below code each nested li is only as wide as it's text + margin.

I'd like all of the li's to be as wide as the widest li under the parent ul.

eg:

<ul id="menu">
    <li <a href="#" title="Menu a">Menu a</a></li>
    <li <a href="#" title="Menu b">Menu b</a></li>
    <li <a href="#" title="Nested Menu">Nested Menu</a>
        <ul>
            <li <a href="#" title="Menu Item">Menu Item</li>
            <li <a href="#" title="Long Menu Item">Long Menu Item</a></li>
            <li <a href="#" title="Longer Menu Item">Longer Menu Item</a></li>
        </ul>
    </li>
    <li <a href="#" title="Menu z">Menu z</a></li>
</ul>

with css:

<style type="text/css" media="all">
* {
    padding:0; 
    margin:0;
}
body, html {
    width: 100%;
    height: 100%;
}
#wrapper {
    width: 800px;
    height: 100%;
    margin: auto;
}
#menu {
    margin: 0 0 0 8px; 
    padding: 0;
    font-size: 14px; 
    font-weight: normal;
}

#menu ul {
    list-style-type:none; 
    list-style-position:outside; 
    position:relative; 
    z-index:300; 
    height: 32px;
    font-weight:bold; 
    white-space: nowrap;
    padding:0;
} 
#menu a {text-decoration:none; 
    line-height: 32px;
} 
#menu a:hover {

} 
#menu li {
    float:left; 
    position:relative; 
    display: inline; 
    height: 100%; 
    list-style-type: none; 
    padding: 0 20px;
    background: #ccc;
} 
#menu ul {
    position:absolute; 
    display:none; 
    left:0px;
    background: #BDCCD4;
    width:100%;
} 
#menu ul a, #menu li a {
    display: block;
}
#menu li ul {
    background: #BDCCD4;
    display:block;
}
#menu li ul a {
    font-weight: normal;
    height:auto; 
    float:left;
} 
#menu ul ul {
    padding: 0 9px;
    display:block;
} 
#menu li ul li {
    padding: 0 9px;
    background: #BDCCD4;
}
#menu li:hover {
    background: #ddd;
    height: 32px;
}
#menu li li:hover, #menu li li li:hover {
    background: #ddd;
    height: 32px;
}
#menu li a:link, #menu li a:visited {
    text-decoration: none;
    color: #003E7E;
    margin: auto;
}

A: 

Simply adding width: 100% for #menu li ul li works for me. To make it work for even longer items, use width: auto on #menu li ul. EDIT 2: Added padding workaround.

The new CSS:

<style type="text/css" media="all">
* {
    padding:0;
    margin:0;
}
body, html {
    width: 100%;
    height: 100%;
}
#wrapper {
    width: 800px;
    height: 100%;
    margin: auto;
}
#menu {
    margin: 0 0 0 8px;
    padding: 0;
    font-size: 14px;
    font-weight: normal;
}

#menu ul {
    list-style-type:none;
    list-style-position:outside;
    position:relative;
    z-index:300;
    height: 32px;
    font-weight:bold;
    white-space: nowrap;
    padding:0;
}
#menu a {text-decoration:none;
    line-height: 32px;
}
#menu a:hover {

}
#menu li {
    float:left;
    position:relative;
    display: inline;
    height: 100%;
    list-style-type: none;
    padding: 0 20px;
    background: #ccc;
}
#menu ul {
    position:absolute;
    display:none;
    left:0px;
    background: #BDCCD4;
    width:100%;
}
#menu ul a, #menu li a {
    display: block;
}
#menu li ul {
    background: #BDCCD4;
    display:block;
    width: auto;
}
#menu li ul a {
    font-weight: normal;
    height:auto;
    float:left;
}
#menu ul ul {
    padding: 0 0 0 9px;
    display:block;
}
#menu li ul li {
    padding: 0 9px;
    background: #BDCCD4;
    width: 100%;
}
#menu li:hover {
    background: #ddd;
    height: 32px;
}
#menu li li:hover, #menu li li li:hover {
    background: #ddd;
    height: 32px;
}
#menu li a:link, #menu li a:visited {
    text-decoration: none;
    color: #003E7E;
    margin: auto;
}

The result is here: http://jsfiddle.net/y83zm/2/ EDIT 2 Added fix to solve a weird padding issue, see http://jsfiddle.net/y83zm/5/

MvanGeest
hey, thanks MvanGeest - that works with the test code I supplied but not with my real code.If you add another li with text of "What about a much longer title" the background gets cut off.Is there any way to avoid this?cheers
unhitched
Could you edit the jsFiddle I provided to make it go wrong, click "Update" and post the new link? Also, what browser(s) are you targeting? I cannot give any guarantee for IE6.
MvanGeest
Never mind, did it myself and edited the solution. Does that help? Works for me in Firefox. (Oh, and if the solution works, could you mark it as such?)
MvanGeest
wow - never used that before and very handy:> http://jsfiddle.net/y83zm/4/
unhitched
Well, take a look at http://jsfiddle.net/y83zm/2/. Does that satisfy your requirements? It's actually an even longer item :) I added the extra code to the solution above!
MvanGeest
so close! it now spreads out too far. Anyway to restrict it to text + padding?
unhitched
Weird. Somewhere the value for the padding gets doubled. How about http://jsfiddle.net/y83zm/5/ ? I worked around the problem by redefining the padding to `padding: 0 0 0 9px;` Please do try a few different texts.
MvanGeest
unhitched
A: 

To make all of the list items the same length as the longest, you will need to manually set the widths. There is no pure CSS method of achieving this automatically as far as I know.

li{width:100%} Will make the list items fill the width of their container. If that is not set, then it will be the width of the user's browser window.

danixd
Have you checked my jsFiddle? Works fine in Firefox 3.6 and Internet Explorer 8. Has problems in IE7, but width-unrelated.
MvanGeest
damn - that makes it hard with dynamic content!
unhitched
Nice. I suppose a conditional stylesheet could be added to set the width for <=IE 7
danixd
hey guys,thanks for all your suggestions - I ended up setting the width manually only because width:100% didn't work in Chrome.cheers
unhitched
A: 

You'll need to use JavaScript to set all LIs the same width as the widest LI. Here's the code if you want to use the jQuery library:

$(document).ready(function(){
  $("#menu > li > ul").each(function() { // Loop through all the menu items that got submenu items
    var Widest=0; // We want to find the widest LI... start at zero
    var ThisWidth=0; // Initiate the temporary width variable (it will hold the width as an integer)

    $($(this).children()).each(function() { // Loop through all the children LIs in order to find the widest
      ThisWidth=parseInt($(this).css('width')); // Grab the width of the current LI

      if (ThisWidth>Widest) { // Is this LI the widest?
        Widest=ThisWidth; // We got a new widest value
      }
    });

    Widest+='px'; // Add the unit

    $(this).parent().css('width',Widest);
    $(this).children().css('width',Widest);
  });
});

CSS change:

#menu li ul li {
  padding: 0 9px;
  background: #BDCCD4;
  padding: 0 20px;
}

Check it out at JSFiddle.

Edit: Fixed my misunderstanding. :)

Gert G
very cool - works well with "#menu li" but not with "#menu li ul li" or is that just me?
unhitched
You'll get the parent LI the same width as the widest submenu LI. If this is not desirable, the you should go with the pure CSS solution. :)
Gert G