tags:

views:

1308

answers:

7

Although elements like <div>s normally grow to fit their contents, using the float property can cause a startling problem for CSS newbies: if floated elements have non-floated parent elements, the parent will collapse.

For example:

<div>
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>

The parent div in this example will not expand to contain its floated children - it will appear to have height: 0.

How do you solve this problem?

I would like to create an exhaustive list of solutions here. If you're aware of cross-browser compatibility issues, please point them out.

Solution 1

Float the parent.

<div style="float: left;">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>

Pros: Semantic code.
Cons: You may not always want the parent floated. Even if you do, do you float the parents' parent, and so on? Must you float every ancestor element?

Solution 2

Give the parent an explicit height.

<div style="height: 300px;">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>        
</div>

Pros: Semantic code.
Cons: Not flexible - if the content changes or the browser is resized, the layout will break.

Solution 3

Append a "spacer" element inside the parent element, like this:

<div>
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
    <div class="spacer" style="clear: both;"></div>
</div>

Pros: Straightforward to code.
Cons: Not semantic; the spacer div exists only as a layout hack.

Solution 4

Set parent to overflow: auto.

<div style="overflow: auto;">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>        
</div>

Pros: Doesn't require extra div.
Cons: Seems like a hack - that's not the overflow property's stated purpose.

Comments? Other suggestions?

+2  A: 

I usually use the "overflow: auto" trick; although that's not, strictly speaking, the intended use for overflow, it is kinda related - enough to make it easy to remember, certainly. The meaning of "float: left" itself has been extended for various uses more significantly than overflow is in this example, IMO.

Bobby Jack
+6  A: 

As far as I'm aware the definative solution to this problem can be found over at http://www.positioniseverything.net/easyclearing.html. Hope this helps.

+1  A: 

I use 2 and 4 where applicable (i.e. when I know the content's height or if overflowing doesn't harm). Anywhere else, I go with solution 3. By the way, your first solution has no advantage over 3 (that I can spot) because it isn't any more semantic since it uses the same dummy element.

By the way, I wouldn't be concerned about the fourth solution being a hack. Hacks in CSS would only be harmful if their underlying behaviour is subject to reinterpretation or other change. This way, your hack wouldn't be guaranteed to work. However in this case, your hack relies on the exact behaviour that overflow: auto is meant to have. No harm in hitching a free ride.

Konrad Rudolph
Oops - I removed the dummy element in the first solution. That was a mistake. Thanks for pointing it out.
Nathan Long
+1  A: 

Although the code isn't perfectly semantic, I think it's more straightforward to have what I call a "clearing div" at the bottom of every container with floats in it. In fact, I've included the following style rule in my reset block for every project:

.clear 
{
   clear: both;
}

If you're styling for IE6 (god help you), you might want to give this rule a 0px line-height and height as well.

Plan B
A: 

The ideal solution would be to use inline-block for the columns instead of floating. I think the browser support is pretty good if you follow (a) apply inline-block only to elements that are normally inline (eg span); and (b) add -moz-inline-box for Firefox.

Check your page in FF2 as well because I had a ton of problems when nesting certain elements (surprisingly, this is the one case where IE performs much better than FF).

DisgruntledGoat
A: 

rather putting overflow:auto on the parent, put overflow:hidden

The first css I write for any webpage is always:

div {
  overflow:hidden;
}

and i never have to worry about it

tybro0103
A: 

The problem happens when a floated element is within a container box, that element does not automatically force the container’s height adjust to the floated element. When an element is floated, its parent no longer contains it because the float is removed from the flow. You can use 2 methods to fix it:

  • {clear: both;}
  • clearfix

Once you understand what is happening, use the method below to “clearfix” it.

.clearfix:after {
    content: ".";
    display: block;
    clear: both;
    visibility: hidden;
    line-height: 0;
    height: 0;
}

.clearfix {
    display: inline-block;
}

html[xmlns] .clearfix {
    display: block;
}

* html .clearfix {
    height: 1%;
}

.

Demonstration :)

Sarfraz