views:

121

answers:

3

This is an expansion of a question I posted a while ago: http://stackoverflow.com/questions/3275997/fitting-a-uls-width-to-accommodate-the-menu-items

Is there a snippet of jQuery code that can adjust the width of every <ul> inside a certain <ul> to make sure the <li> items don't overflow? The menu looks something like this:

<ul id="menu">
  <li>
    <a href="javascript:;">Menu 1</a>
    <ul>
      <li><a href="javascript:;">Item 1<a></li>
      <li>
        <a href="javascript:;">Subitem 1</a>
        <ul>
          <li><a href="javascript:;">Subsubitem 1</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

If I don't adjust the <ul> correctly, the layout looks messed up as shown here:

Site menu

You can take a look at the site I'm developing here if you need more information about the CSS or the general structure of the web page.

A: 

If you remove the line-height property from:

ul#menu > li > ul li {
  color:black;
  font-size:10pt;
   /*line-height:30px;*/
  text-align:left;
}

It displays fine or set the line-height to lesser value such as 20px

Sarfraz
I'd like all menu items to have the same height, so I'm afraid that this is not an option for me.
Pieter
You can set the height like this then `$('ul#menu li').css('height', '20');` You can adjust the value.
Sarfraz
But when the height is fixed (which is what I want), then it's possible for text to overflow. I'd like the width to be adjusted to fit the text onto one line, the height should remain the same.
Pieter
`$('ul#menu li').css('width', '200');`
Sarfraz
Try setting `width: auto;` and specify fixed height;
Tom
`width: auto` doesn't seem to change the situation. This doesn't prevent text from spilling over onto a new line instead of having the menu being resized to fit the text on one line. @Sarfraz: what if I'm dealing with text that requires more space than 200px?
Pieter
@Pieter: Try setting the width in percents then rather than pixels.
Sarfraz
That makes the `<li>` width relative to the underlying `<ul>`, if I remember my CSS theory correctly. That still doesn't ensure the menu is wide enough to fit every menu item on one line of text.
Pieter
+2  A: 

The width problem actually stems from the width set at the top level here:

ul#menu > li {
  display: block;
  float: left;
  background: url(img/menuitem.png) top left;
  width: 104px;                                 /* here's the issue */
  height: 36px;
  margin-right: 1px;
  text-align: center;
  position: relative;                           /* add this */
}

Since it has a width specified, and its child is in the normal flow, its child is obeying its width, rather than scaling by itself. What you can do is take the child out of the flow, by adding position: realtive; like I have in the above style, then give the child <ul> a position: absolute, like this:

ul#menu > li ul {
  position: absolute;
  top: 36px;              /* top <li> is 36px, go down that much */
}

Then finally, so the anchor text gets a full background, give it a white-space rule like this:

ul#menu > li > a, ul#menu > li > ul a {
  display: block;
  text-decoration: none;
  white-space: nowrap;
}

Here's what the result looks like: alt text

Nick Craver
Great solution, no Javascript involved.
hitautodestruct
@hitautodestruct this solution has a couple of bugs under ie6
Happy
I'm almost there, but there's something odd going on with my CSS. Have a look at this screenshot from Chrome's element inspector: http://a.imageshack.us/img6/6159/inspector.jpg
Pieter
@Ignatz ie6 is dead. Supporting it is like caring for a corpse.I don't understand what the problem is from the chrome screen shot.
hitautodestruct
@Pieter - Can you shoot me a link to the modified CSS to take a look? I'm still seeing the original on the site link in the question
Nick Craver
I uploaded the modified CSS file to the site. Have you tried hitting CTRL+F5? Anyway, you can find the stylesheet here: http://www.pieterdedecker.be/labs/vspwpg/wp-content/themes/vspw/style.css
Pieter
@hitautodestruct Chrome ignored certain CSS code, as visualized by those three CSS declarations that were struck out. The declarations that were effected are `display: block; text-decoration: none; white-space: nowrap;`.
Pieter
@Pieter - You're seeing that in the developer tools because `ul#menu > li > a, ul#menu > li > ul a {` is repeated in your stylesheet, so the first definition of those styles are ignored, look at like 59 and line 89...apologies on the caching, that was my end, Chrome 6 dev version has messed up caching at the moment, even with Ctrl+F5.
Nick Craver
@Pieter - Also the old styles for `ul#menu > li ul {` are at line 97, so they're overriding the corrected styles at line 72 :)
Nick Craver
Oops, that makes total sense. Sheesh, I gotta stay focused when editing my CSS. But hey, thanks for solving my issue! The bounty is yours.
Pieter
+1  A: 

This is all you need to do (and the spacing should be consistent with your theme):

ul#menu > li > ul {
  position: absolute;
  top: 37px;
}
jackocnr
This is not the only issue, it would put the element at the top of the page, I've already addressed this fully in my answer :)
Nick Craver