tags:

views:

314

answers:

3

Hello. I have a complicated multi-level menu. The (absolutely positioned) right hand menu items are spilling out of the (absolutely positioned) container in IE and Opera, but not in Firefox (or Chrome or Safari); I suspect that Firefox is wrong because I don't see why an absolutely positioned element should have its dimensions constrained by an absolutely positioned ancestor. However, it is the Firefox effect that I am trying to achieve.

My constraints are: I know the width of .outer; however, I don't know the content (and therefore width) of any of the spans which should determine the width of .middle. I don't know the content (and therefore width) of any of the .inner divs, however, their width must not affect the width of the parent .middle. The left hand edge of .inner must line up with the left hand edge of it's sibling span. Ie, it's a two-level menu, whereby the 2nd level must be constrained within an ancester's border, but each item in the first level must not be affected by the width of its child menu.

What changes to I need to make to constrain the inner div to the boundaries of the outer div in IE? See a simplified version of the code below. In the original markup, .outer was a ul and .middle was a li.

<head>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
            list-style-type: none;
        }
        .outer{
            border: solid 1px black;
            width: 200px;
            position: absolute;
        }
        .outer div
        {
        border: solid 1px green;
            float: left;
        }
        .inner
        {
            position: absolute;
        }
        .inner p
        {
            border: solid 1px red;
        }
        span{
            display: block;
            padding: 0 10px;
        }
        .hide
        {
            display: none;
        }
    </style>
</head>
<body>
    <div class="outer">
        <div class="middle">
            <span>outer</span>
            <div class="hide"><p>lots and lots of inner text</p></div>
        </div>
        <div class="middle">
            <span>outer</span>
            <div class="hide"><p>lots and lots of inner text</p></div>
        </div>
        <div class="middle">
            <span>outer</span>
            <div class="inner"><p>lots and lots of inner text</p></div>
        </div>
    </div>
</body>
A: 

I think actually Firefox is correct, but I'm no CSS expert. According to w3schools, the default implementation should allow content to render outside of the containing box if it's too wide for it.

It depends what you want the overflowing content to do. Have you tried setting the overflow CSS property on your outer DIVs? Or set the width on the inner DIVs?

Andy Shellam
I want the content of the inner div to wrap onto multiple lines. I can't set the width of the inner divs because they're variable (this is one solution that I have already. Set right = 0 and fix the width.
darasd
What about max-width? You still get your variable width but it doesn't exceed max-width and *should* wrap.
Andy Shellam
I'm not sure you can do it without fixing the width of the `.inner` divs... but let me play some more.
Scott Cranfill
max width still doesn't work because I don't know the width of the parent divs (determined by the span). try setting the inner max-width to 100px and then the padding of the span to 15px and see it break.
darasd
I don't think it's possible to achieve what you want without either (a) fixing some widths, or (b) using JavaScript to grab the rendered widths on load and then set the CSS properties accordingly.
Scott Cranfill
I don't have IE available right now but Firefox, Chrome and Opera all look the same.
Rob
You say you don't know the width of the outer DIVs, but you're specifying it: ".outer{...width: 200px;" So couldn't you say "max-width: 200px" on the inner DIVs?
Andy Shellam
the outer container contains all of the inner divs. i know the width of .outer, but i don't know the widths of any of the elements that it contains. if i set .inner max-width to the same as .outer, then if that .innner is not the first in the list, then it will break out of .outer.
darasd
darasd
A: 

You can do this by setting .inner to position: relative. It's not evident from your code sample why you selected absolute in the first place, but any manual positioning you want to do should be achievable with relative. Instead of setting the top, right, bottom, or left properties relative to the origin of its containing block, set them relative to where .inner would normally be positioned in the flow.

Hope that helps!

Scott Cranfill
relative causes the inner div to stretch its parent, which causes the menu structure to go wrong. The inner div must have no affect upon the width of its parent, and vice versa. The inner div's parent should only determin the position of the inner div.
darasd
A: 

I have found a partial solution, applying position relative to .middle. This should be applied to IE. Unfortunately, this messes around with the padding, but hopefully this will be a smaller issue to fix. This version is using the correct elements - not just divs.

<head>
    <title></title>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
            list-style-type: none;
        }
        .outer{
            border: solid 1px black;
            position: absolute;
            width: 200px;
        }
        .inner
        {
            position: absolute;
            width: auto;
        }
        .middle
        {
            border: solid 1px green;
            float: left;
        }
        .inner *
        {
            border: solid 1px red;
        }
        span{
            display: block;
        }
        .hide
        {
            display: none;
        }
    </style>
    <!--[if IE]>
        <style type="text/css">
            .middle{
                position: relative;
            }
        </style>
    <![endif]-->
</head>
<body>
    <ul class="outer">
        <li class="middle">
            <span>outer</span>
            <ul class="hide"><li>lots and lots of inner text</li></ul>
        </li>
        <li class="middle">
            <span>outer</span>
            <ul class="hide"><li>lots and lots of inner text</li></ul>
        </li>
        <li class="middle">
            <span>outer</span>
            <ul class="inner"><li>lots and lots of inner text</li></ul>
        </li>
    </ul>
</body>
darasd