Why Containers Don’t Clear Themselves

Published by Chris Coyier

One of the hurdles (and "ah-ha" moments) in learning CSS is this business about clearing floats. If you have no idea what I'm talking about, check out the classic All About Floats.

I specifically want to talk about the issues of "collapsing", that is, how elements that contain floated items don't take those floated items into account in calculating their height. For example a parent element that only contains floated items will have a zero height. This is surprising and confusing to those new to CSS, and seems to be counter-intuitive.

Solving it is typically trivial. Using any overflow value of hidden or auto on the parent will "fix" it. The clearfix is also popular.

But these "fixes" give rise to the thinking that this behavior is "broken"1 to begin with. Confusing? Sure. Should be better options for control? Absolutely. Broken? Not really. If all containers expanded to contain their floated decedents, we would be complaining even worse, and the problem might be harder to work around.

The classic example

We'll use this example presented by Eric Meyer seven years ago.

<p>
 ...text...
 <img src="sunset.jpg" class="callout" />
 ...text...
</p>
<p>
 ...text...
</p>

The callout class, for example, would float the image to the left and apply some margins. This is what we get now:

That is exactly what we would want, the correct text reflow. In order for that to happen, that upper paragraph needs to "collapse" as it were, and let the floated image stick out of the bottom of it.

If the upper paragraph automatically expanded to contain the float, we'd be left with this:

As Eric said:

That's something designers would never have accepted.

And I agree. This could have been an even worse problem, assuming no fancy workaround could have been found to work around it.

Should there be a better solution?

Yeah, probably. I've seen suggested:

overflow: contain;

That might work, but what about if you wanted to hide horizontal overflow? We already have overflow: hidden, which already contains floats, which works, but then that's a bit semantically confusing. There could be a whole new attribute like

contain: floats | collapse | inherit;

But I dunno, they can't just go adding new attributes all the time, so that would have to be taken under serious scrutiny.


1 I'd also like to add here that I hear people say that "floats take the element out of the document flow" fairly often, which isn't true. Floated elements still affect inline elements (that's kind of the point) as well as other floated block level elements. If floated elements were "removed from the document flow", they wouldn't affect anything (like absolutely positioned elements).