Everything you Know about Clearfix is Wrong
This article was first published on carsonified.com (04-12-2010).
Note that throughout this article, when I use the term “IE” it refers to IE versions that “support” hasLayout.
What Does it Do?
clearfix works like this:
- In browsers that support the pseudo-element
:after
, it generates content (placed after the content in the element) that is styled to clear floats. In short, it works more or less the same as if you were inserting<div style="clear:both"></div>
before the element’s closing tag. - In IE, it gives the element a layout, hence it establishes a new block formatting context which will contain floats (see below).
So What?
The latter means that in IE, and in IE only, clearfix will trigger a different construct. This is because a “block formatting context”:
- contains float
- prevent collapsing margins
- does not overlap any floats in the same block formatting context (see 9.5)
How Bad is That?
It really depends on the layout and the styling of elements. You might go from “uh oh!” to “WTF sacrebleu!”. For example, in this simple demo (meant to illustrate #1 and #2 above) there are a few display issues between IE and so-called modern browsers:
- In Mozilla, WebKit, etc.:
- The three headings are not vertically aligned,
- The gap above the wrapper (which contains the background image) is more than 20px high.
- The floated box appears outside of the wrapper.
- In IE:
- The three headings are vertically aligned,
- The gap above the wrapper is half the size it is in modern browsers.
- The background image is painted behind the floated box.
What Gives?
The explanation is simple:
- In IE:
- The wrapper has a layout (because of its width), so it creates a new block formatting context. This prevents the margin of the
<p>
(the black box) from collapsing with the margin of the heading in the last container. In short, the gap above the wrapper is the bottom margin of the black box (the<p>
). - The wrapper contains the float because – as per the spec – block formatting contexts always contain floats.
- The wrapper has a layout (because of its width), so it creates a new block formatting context. This prevents the margin of the
- In modern browsers:
- All elements belong to the same block formatting context so adjacent margins collapse. The heading’s margin “sticks out” of the wrapper to butt against the
p
. Unlike in IE, it is that margin (not the one on the black box) that creates the gap above the wrapper. - For the same reason, the floated box is not contained inside the wrapper.
- All elements belong to the same block formatting context so adjacent margins collapse. The heading’s margin “sticks out” of the wrapper to butt against the
There is no bug involved here. If the visual rendering is different between IE and modern browsers it is simply because we are styling the wrapper differently across the board.
If you check this new demo page, where the wrapper creates a new block formatting context in IE as well as in modern browsers, things look much better (yes, the space in IE below the floated box is a bug, it is there because the wrapper has a layout).
What has this got to do with clearfix?
Let’s assume we do not know much about block formatting contexts and instead of styling the wrapper as we did in the previous demo page we apply the clearfix method to the div
that contains the floated box.
As I write this, I wonder if you would be able to guess what clearfix is about to do to our layout. Anyway, the result can be seen in this demo page where clearfix is applied.
What Happened?
The floated box is contained, but the layout breaks in IE, the middle column is now below the side bars. This is because as per section 9.5 of the spec (see above), a block formatting context does not overlap floats in the same block formatting context.
The middle column gained layout (via clearfix), hence it creates a new block formatting context which cannot fit between the two floats, so it drops below them.
At this point, most authors find out that removing the padding declarations fixes what they believe is a bug, so they use a Conditional Comment and reset the padding values for IE.
Not once have they questioned clearfix, and as far as they know their construct is more or less the same across browsers (apart the padding they had to zero out and the collapsing margin they had to fix somehow).
What can I Do?
Making sure that elements are styled the same across browsers is styling 101. It is the first step toward achieving cross-browser compatibility.
Styling both the wrapper and the middle column to create block formatting contexts (e.g.: styling the wrapper with display:inline-block
and the middle column with overflow:hidden
) does the trick, as this last demo shows.
Wrap Up
Weak constructs are most often due to the fact that people do not know what block formatting contexts are and what they do.
Too often, authors trigger hasLayout without thinking of adding the necessary styling to create the same rendering across all browsers. Because of this, they end up adding IE specific declarations to “patch” their styling.
This does not mean we should avoid “clearfix” at all costs though. It is a great tool which is safe to use as long as we remember that besides containing floats, it may also prevent collapsing margins and will “escape” surrounding floats in IE.
I’ve been using clearfix myself to style modal windows and the like, usuallly when I know there is no float in the same block formatting context as the element I am styling. Hey, I even rely on it for my CSS framework.
More on hasLayout, block formatting contexts, and containing floats
- HasLayout Overview
- Block formatting context
- Visual formatting model
- Another look at enclosing floats inside containers