I’m trying to create a navigation menu with a subnav containing floated lists. I’m using a floated ul inside an absolute positioned div, inside a floated li with relative positioning. The div needs to be absolutely positioned, I’m using relative positioning on the li because I want the absolute positioned divs to be placed relative to the list items and not the overall page. If I remove position: relative from the li then the lists float side by side in the div (exactly what I want) but the div is then not placed under the relevant menu item. With position: relative the div is placed where I want but the lists are stacked on top of each other. This is all in Firefox and Chrome.
If I explicitly define the width on the div to be big enough to contain both lists side by side, it works properly, but this isn’t much help as the lists will be dynamically generated.
Here’s some test code I’ve been using trying to simplify the problem as much as possible:
The only sure way you can accomplish what you need the child UL elements to do would be to define a static width on the parent DIV as by default absolutely positioned elements don’t inherit any height or width which would cause floats to act like the display property with a value of block. Have a look at the following jsFiddle which i have added the static width to:
The only sure way to to accomplish this would be to use JavaScript and calculate the total width of the child elements and then set it on the parent DIV which is a dirty fix but will work.
Ok thanks for the help. I’ve hacked together some javascript which seems to work ok, is there anything stupid I’ve done here that might break anything? I’m executing it via body onload=.
function setsubnavwidth() {
//Sets width on container divs for navigation submenus
var subnavdivs=document.getElementsByClassName("listcontainer");
for (var i = 0; i < subnavdivs.length; i++) {
var subnavuls=subnavdivs[i].childNodes;
var totalWidth=0
for (var j = 0; j < subnavuls.length; j++) {
if (subnavuls[j].tagName=="UL") {
totalWidth = totalWidth+subnavuls[j].offsetWidth
}
}
subnavdivs[i].style.width=totalWidth;
}
}
Did I misunderstand what you wanted (quite likely)?
I thought you wanted the nested uls to align in horizontal blocks like the attached image which is what the code produces. Did I miss something important again?
Strange it’s working more or less everywhere for me except for a bug in IE7 which I’ve addressed in the code below. The version I posted above was working in ie5.5, 1e6, 1e8, 1e9, firefox 3.6, 4, 5, 6,7,8, safari and chrome pc and mac.
It won’t work in Firefox 2 but that’s dead and buried long ago.
Sorted it, you left the link to my external stylesheet in, and since I was testing in the same folder that was breaking it. Thanks for the help, now to try and understand why it works
Thanks for the help, now to try and understand why it works
The basics are that instead of floating the uls we make them inline-blocks which mean that they align side by side just like words would. They also have the same behaviour as words in that if you set white-space:nowrap then the words won’t wrap to a new line and neither will the inline-block elements and that forces them to stay on the same line.
The problem with absolute elements is that they are a “shrink to fit element” and therefore the floats don’t line up horizontally as there is no actual space to the right of the float above. There was also a solution in setting the parent li to a great big width (or using large negative margins) and then hiding the overflow but would have caused some issues.