views:

430

answers:

6

Hi, I am trying to layout a header for a web site and I would like to have 4 containers in the header for dropping various user controls into.

The 4 containers need to be positioned top left, top right, bottom left and bottom right inside the main the header container.

So far I can acheive this, the bit I can't do is that the bottom left and bottom right containers need to be aligned with the bottoms of their containers at the same level.

If I assign a height to #Bottom it works fine but I don't want to do this as I cannot predict what controls will be on the page and therefore won't know what height to set.

It needs to work in IE7.

I hope that all makes sense.

I have created a sample app to demonstrate the problem...

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
    <style type="text/css">

    .clearFloats
    {
        clear:both;
    }

    #topLeft
    {
     float:left;
        border: 1px solid blue;
        height:50px;
    }

    #topRight
    {
     float:right;
        border: 1px solid blue;
        height:50px;
    }

    #bottom
    {
     position:relative;
        border: 1px solid green;
    }

    #bottomLeft
    {
     float:left;
        border: 1px solid red;
        position:absolute;
        top:0;
    }

    #bottomRight
    {
     float:right;
        border: 1px solid red;
        position:absolute;
        top:0;
        right:0;
    }

    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
     <div id="topLeft">top left</div>
     <div id="topRight">top right</div>
     <div class="clearFloats" />
     <div id="bottom">
      <div id="bottomLeft">bottom left</div>
      <div id="bottomRight">bottom right<br />Some content<br />some more content</div>
      <div class="clearFloats" />
     </div>
    </div>
    </form>
</body>
</html>
A: 

Your positioning between bottomLeft and bottomRight is not consistent:

#bottomLeft
{
    bottom:0;
}

#bottomRight
{
    top:0;
}

If you want bottomLeft to behave like bottomRight, they should have the same vertical positioning. Or are they both wrong?

Adam Bellaire
Apologies, you are right they should both be top, however that still doesn't solve the problem. I'll edit the code. Thanks.
Si Keep
Since you don't have content in the example, it's hard to see what the problem actually is. They don't overlap, and they appear to be at the corners of your content. Can you point out what's wrong in the image example (after updating it)?
Adam Bellaire
So in the image I want the 'bottom left' text to be at the same level as the 'some more content' text, i.e as if 'bottom left' was actually '<br/><br/>bottom left'.
Si Keep
I am trying to acheive this...http://www.flickr.com/photos/skeep/3131426012/
Si Keep
+3  A: 

Sorry I can't be of more help, but I'm not sure this is possible given the constraints that you have. The main problem is that you want to align to the bottom of the bottom div, but since both bottomRight and bottomLeft are positioned absolute, the items overflow the bottom div. Therefore, using the bottom property aligns them with their bottoms on the (empty) green line in your example.

The only think I can come up with requires you to know which of your two elements will be taller. You don't have to know the specific height, but if you can predict which is taller and set it not to use position:absolute, then the container will function and the other (smaller) element will drop into place. Given your example, if you know that bottomRight will be taller:

#bottomLeft
{
    float:left;
    border: 1px solid red;
    position:absolute;
    bottom:0;
}

#bottomRight
{
    float:right;
    border: 1px solid red;
}

If you don't know which will be taller ahead of time, I don't know what else you can do. You need some content inside the bottom div to give it the proper height, so that the "position: absolute; bottom: 0" style will have the desired effect.

Adam Bellaire
+3  A: 

As Adam said to have a pure CSS solution you would need to know which bottom div was going to have more text in it.

Below I have used javascript to check if bottomLeft has more content and then flip the styling if it does...try this below...and then try changing out so that bottomLeft has more content and then refresh. Hope this helps.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
    <style type="text/css">

    .clearFloats
    {
        clear:both;
    }

    #topLeft
    {
        float:left;
        border: 1px solid blue;
        height:50px;
    }

    #topRight
    {
        float:right;
        border: 1px solid blue;
        height:50px;
    }

    #bottom
    {
        width:100%;
        border: 1px solid green;
        position:relative;
    }


    #bottomLeft
    {
        float:left;
        border: 1px solid red;
        position:absolute;
        bottom:0;
    }

    #bottomRight
    {
        float:right;
        border: 1px solid red;
    }

    </style>
</head>
<script type="text/javascript">

    window.onload = function() {
     var leftBot = document.getElementById('bottomLeft');
     var rightBot = document.getElementById('bottomRight'); 
     //if the left is actually bigger than swap out their styling
     if (leftBot.innerHTML.length > rightBot.innerHTML.length) {
      leftBot.style.position='static';
      rightBot.style.position='absolute';
      rightBot.style.bottom = 0;
      rightBot.style.right = 0; 
     }
    }

</script>

<body >
    <form id="form1" runat="server">
    <div id="header">
        <div id="top">
            <div id="topLeft">top left</div>
            <div id="topRight">top right</div>
        </div>
        <div class="clearFloats" />
        <div id="bottom">
                <div id="bottomLeft">bottom left</div>
                <div id="bottomRight">bottom right<br />Some content<br />some more content<br/><br/>more more</div>
                <div class="clearFloats" />
        </div>
    </div>
    </form>
</body>
</html>
Jack
A: 

I might be reading this way wrong but why not do this. *warning values need changed just concept:

CSS:

#header{
  height:150px;
  width:350px;
  position:relative;
}
#header #topleft{
  position:absolute;
  top:0;
  left:0;
}
#header #topright{
  position:absolute;
  top:0;
  right:0;
}
#header #bottomleft{
  position:absolute;
  left:0;
  bottom:0;
}
#header #bottomright{
  position:absolute;
  right:0;
  bottom:0;
}

HTML:

<div id="header">
 <div id="topleft"></div>
 <div id="topright"></div>
 <div id="bottomleft"></div>
 <div id="bottomright"></div>
</div>
Bruno43
A: 

Thanks everyone for your time.

I have selected Adams answer as at the moment I can predict that the height of the bottom right container will be bigger than the bottom left so that would work.

I also like the javascript solution from Jack.

Ultimately I think I am trying to be too flexible here. Perhaps what I should be doing is having a series of user controls that define the various header layouts that are possible and then having one large bottom panel and dropping the relevant control in there. Each of the series of user controls could then be layed out exactly as the content would be largely static.

Si Keep
What was Bruno's javascript solution?
Jack
Sorry it was yours Jack, my apologies.
Si Keep
A: 

When I have a layout issue I cannot solve in 1 hour I go back using tables. In your case using table would be a good solution because IMO it feels more stable than the other solutions.

An other idea would be putting your top 2 divs in a container div, the bottom 2 divs in another container div and make one float left, the other right. This way you do not have to use absolute positioning. (Make sure that the container has overflow:auto or if you want it to work in IE6 put an element with the style "clear: both" between the two divs and the containing div)

Germstorm