28 May 2012

CSS Relative Positioning and Collapsing DIV

The HTML/CSS pattern of nesting a floating div element in a div element can cause the problem of collapsing the parent div element, and the child div doesn't position as expected (i.e., relative to the parent div).

Namely, this doesn't work as expected:
<div class="parent" style="margin: auto; width: 50%;">
  <div class="child" style="float: left; left: 1em; top: 1em; width: 50%;">
  Hi!
  </div>
</div>

First problem, the parent div collapses to zero height.  There are two solutions:

1) Apply the overflow: auto style to the parent div, but this can sometimes introduce scroll bars with the nested div moves "outside" the "normal" area of the parent div.

2) Add a "clearing" empty div element.  This is more predictable, I've found, but introduces a semantically meaningless element.  E.g.:
<div class="parent" style="margin: auto; width: 50%;">
  <div class="child" style="float: left; left: 1em; top: 1em; width: 50%;">
   Hi!
  </div>
  <div class="clearing" style="clear: both; height: 1px; overflow: none;">
  </div>
</div>
The extra styles besides clear: both in the clearing div is for compatibility with old Internet Explorer 6 browsers.

Second problem, the child div is floating left, but it doesn't get nudged down and to the right by 1em each way (via setting top and left).  The solution is to set the child to have the CSS style position: relative, namely as this:
<div class="parent" style="margin: auto; width: 50%;">
  <div class="child" style="position: relative; float: left; left: 1em; top: 1em; width: 50%;">
   Hi!
  </div>
  <div class="clearing" style="clear: both; height: 1px; overflow: none;">
  </div>
</div>

It's also possible to set the child div to have position: absolute (and not floated) but it will be placed absolutely relative to the window's upper-left corner.  To make it relative to the parent div, set the parent div to have position: relative as well, as follows:
<div class="parent" style="position: relative; margin: auto; width: 50%;">
  <div class="child" style="position: absolute; left: 1em; top: 1em; width: 50%;">
   Hi!
  </div>
  <div class="clearing" style="clear: both; height: 1px; overflow: none;">
  </div>
</div>

No comments: