views:

2460

answers:

4

I'm having a strange problem positioning a set of divs inside another div. I think it will be best to describe it with an image.

Inside the black (#box) div there are two divs (.a, .b) that have to positioned in the same place. What I'm trying to achieve is pictured in the first image, second one is the effect I get. It looks like if the divs were floated without clearing or something, which is obviously not the case. Any ideas would be welcome!

Here's the code for this sample:

CSS:

  #box {
   background-color: #000;
   position: relative; 
   padding: 10px;
   width: 220px;
  }

  .a {
   width: 210px;
   position: absolute;
   top: 10px; left: 10px;
   background-color: #fff;
   padding: 5px;
  }

  .b {
   width: 210px;
   position: absolute;
   top: 10px; left: 10px;
   background-color: red;
   padding: 5px;
  }

  #after {
   background-color: yellow;
   padding: 10px;
   width: 220px;
  }

HTML:

    <div id="box">
  <div class="a">Lorem</div>
  <div class="b">Lorem</div>
 </div>

 <div id="after">Hello world</div>
+4  A: 

The problem is described (among other) in this article.

#box is relatively positioned, which makes it part of the "flow" of the page. Your other divs are absolutely positioned, so they are removed from the page's "flow".

Page flow means that the positioning of an element effects other elements in the flow.

In other words, as #box now sees the dom, .a and .b are no longer "inside" #box.

To fix this, you would want to make everything relative, or everything absolute.

One way would be:

.a {
   position:relative;
   margin-top:10px;
   margin-left:10px;
   background-color:red;
   width:210px;
   padding: 5px;
}
Tim Hoolihan
Thanks, but thing is, it's not my choice to use this positioning. I'm using a jQuery plugin that will make a and b absolute positioned.
Justine
can you make #box absolutely positioned? also, jquery could change the css of those items after your plugin runs.
Tim Hoolihan
+1  A: 

The absolute divs are taken out of the flow of the document so the containing div does not have any content except for the padding. Give #box a height to fill it out.

#box {
    background-color: #000;
    position: relative;
    padding: 10px;
    width: 220px;
    height:30px;
}
Emily
Thanks for the tip. The problem with the height is that it doesn't push the "after" div down, just covers it.
Justine
It should. See here: http://ejgejg.com/test/abs.html Are there any other styles applied to after?
Emily
You're right, was just my bad, thank you!
Justine
A: 

One of #a or #b needs to be not position:absolute, so that #box will grow to accommodate it.

So you can stop #a from being position:absolute, and still position #b over the top of it, like this:

<style>
#box {
    background-color: #000;
    position: relative;     
    padding: 10px;
    width: 220px;
}

.a {
    width: 210px;
    background-color: #fff;
    padding: 5px;
}

.b {
    width: 100px; /* So you can see the other one */
    position: absolute;
    top: 10px; left: 10px;
    background-color: red;
    padding: 5px;
}

#after {
    background-color: yellow;
    padding: 10px;
    width: 220px;
}
</style>
<div id="box">
    <div class="a">Lorem</div>
    <div class="b">Lorem</div>
</div>
<div id="after">Hello world</div>

(Note that I've made the widths different, so you can see one behind the other.)

Edit after Justine's comment: Then your only option is to specify the height of #box. This:

#box {
    /* ... */
    height: 30px;
}

works perfectly, assuming the heights of a and b are fixed. Note that you'll need to put IE into standards mode by adding a doctype at the top of your HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
          "http://www.w3.org/TR/html4/strict.dtd"&gt;

before that works properly.

RichieHindle
Thanks you. But like I said in the comment to Tim's answer, I'm using a jQuery plugin that will make a and b absolute positioned, so can't make them not positioned.
Justine
Yes, I ended up adding height to the #box. Thanks!
Justine
A: 

Obrigado !!! Thanks !!!