13 April 2010
Everything you Know about Clearfix is Wrong
What is clearfix?
clearfix is a CSS technique used to contain floats with no structural markup.
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.
- 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.
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.
Note: throughout this article, when I use the term “IE”, it means IE version 5, 6, and 7.
We're big fans of 
Will
# April 13, 2010 - 7:10 pm
To have no float issues with no extra markup is easy, just make sure any items that are floating are within a parent container then set that parent container to overflow:hidden and it fixes any float issues. Ive never had any problems with this technique, even in IE.
Thierry Koblentz
# April 13, 2010 - 7:39 pm
Actually, this is what this article suggests to do (more or less) see section “What can I Do?”.
But note that overflow:hidden has no effect in IE, for IE one needs to give the element a layout.
Jorge
# April 14, 2010 - 3:36 am
That’s where zoom:1 kicks in for IE6 because zoom triggers hasLayout to an element. It works wonders when a parent element collapses because of a floated child. The great thing about it is that you’re not forced to set the width or height and therefore allowing that element to “grow” according to its floated children. It works just as well as overflow:hidden. I haven’t found any negative side effects in all of the years I’ve been using it.
Here’s some code to illustrate the example. Please view the following in IE6. If you’d like to see the code View Source or copy-and-paste the edit link into a browser other than IE6.
http://jsbin.com/udoya (no zoom)
http://jsbin.com/udoya/2 (zoom)
Paul C
# April 14, 2010 - 11:36 am
Just remember that in IE6 for “overflow:hidden” to work, you need to give the container a width value. Other than that, overflow:hidden is the way to go.
Thierry Koblentz
# April 15, 2010 - 2:24 pm
@ Jorge:
I agree with you about zoom, but if it is rarely mentioned in articles and tutorials it is because it does *not* validate.
This is why many authors prefer to use the Holly hack (height:1%;), or a width declaration.
The latter forces you to overwrite the overflow:hidden declaration, the former fails in IE < 5.5.
Thanks
Mal Curtis
# April 21, 2010 - 1:47 am
That’s great 90% of the time, but not ALL the time. If you’re playing absolutely positioned element inside the div, you’ll be cutting off these elements. This happened for me recently when placing ‘validation’ speech bubbles insides form ‘rows’ which had overflow:hidden.
Thierry Koblentz
# April 21, 2010 - 5:44 am
Mal,
There is no technique for modern browsers that comes without caveat. But when positioning elements outside of the container, it is possible to use display:inline plus “width” instead of overflow:hidden.
Sean
# April 13, 2010 - 7:31 pm
Would have to agree with Will. I use overflow tricks to get the containers to behave properly, and have never had a problem. In fact, overflow: ANY_VALID_VALUE will usually work.
Plus, before I used overflow, I would just insert the extra div. I know this caused extra and unnecessary markup, which I know is viewed as the Worst Sin Ever in most web circles, but certainly didn’t seem as horrible as flooding the CSS with a ton of extra and conditional rules.
Sam
# April 13, 2010 - 7:36 pm
Yup, the .clearfix hack has a very simple workaround, as linked to from the original “position is everything” post regarding it: as Will said, overflow:hidden on the container.
Adrian
# April 13, 2010 - 7:37 pm
I have to agree with @Will on this one. I haven’t understood why this is such a big deal for a long time. overflow:hidden has never caused me any problems and doesn’t require extra divs and works in IE6. Can someone explain why this is such a big deal?
Thierry Koblentz
# April 13, 2010 - 8:24 pm
As I mention in my reply to Will, overflow:hidden does *not* work in IE6.
This article is about pointing out that very issue with clearfix, the fact that it does not style things the same across the board.
Using overflow:hidden alone does the exact opposite that what clearfix does.
If it works for you it means you are giving the container a layout without knowing it.
flep
# April 13, 2010 - 9:28 pm
I think people are just ignoring iE6 Thierry. Some are doing without knowing, but probably some are doing knowing it – and for God sakes.
In the agency where I work, iE6 is not supported anymore, even in our website – where we have a message to advice our clients.
Shelomo
# April 13, 2010 - 10:08 pm
for ie6 just use overflow:hidden; _overflow:visible; _height:1%;
Darren
# April 14, 2010 - 12:48 am
It’s almost always possible to add ‘width: 100%’ or ‘width: {some_number}px’ when using the ‘overflow: hidden’ technique which I’d guess is what all the other commentors are doing.
Thierry Koblentz
# April 14, 2010 - 1:06 am
@Darren
Yes, my guess is that they trigger hasLayout via “width”, but the beauty of block formatting contexts is that they can be *width-less* which is a huge plus when it comes to construct.
graham
# April 14, 2010 - 1:36 pm
I’m not sure why you’re wanting *width-less* blocks. As everyone else put, overflow:hidden is used by developers who prefer not to use hacks in their mark up and a much cleaner way to clear floats.
The point of using CSS is to not define layout by markup. It does work in IE6 as long as a width is defined. I’m not sure why width less is a positive thing at all, surely it will cause horizontal scrolling or content to break?
position.fixed
# April 14, 2010 - 1:59 am
You can see why overflow:hidden will not always work within this very comment thread. Sometimes the design calls for overflow to be shown, as in the case of these comment replies that creep out to the right of their parent list.
Thierry
# April 15, 2010 - 2:42 am
@graham
“I’m not sure why you’re wanting *width-less* blocks.”
When it comes to construct, being able to rely on a width-less container allows to dodge problems related to rounding issues or to use padding/border with no concern for the width of the content box.
Think of creating a two column layout (50/50) or a three column layout (1/3, 1/3, 1/3); if a column is width-less it will simply fill the available space. Try 50/50 in IE6 with explicit width, you’ll see what I mean.
John Faulds
# April 13, 2010 - 9:31 pm
As the others point out, most of the time overflow (plus layout for IE) is all that you need, but there are times when it won’t work, e.g. if you have some content that needs to appear outside the bounds of the container like dropdown or flyout menus. Then you have to look at alternative methods. Sometimes you can get away with floating the container. I think I’ve only ever had to use clearfix a handful of times.
Thierry Koblentz
# April 13, 2010 - 10:25 pm
Hi John,
“As the others point out, most of the time overflow (plus layout for IE) is all that you need”
Isn’t what this article is about (see the “What can I do” section)? ;-)
“… there are times when it won’t work, e.g. if you have some content that needs to appear outside the bounds of the container like dropdown or flyout menus”
As suggested in that same section, display:inline-block is an alternative to using float (there are also a few other display values that can be used).
Niels Matthijs
# April 14, 2010 - 6:08 am
>> As suggested in that same section, display:inline-block is an alternative to using float
True to a certain extent, but with more differences than the buts and ifs shown in this article. Inline-block leaves white-space gaps, which (unless you tamper with the actual html) can’t be removed properly as far as I know. So as a real alternative, it’s still pretty weak.
Coincidence maybe, but It was my topic last week:
http://www.onderhond.com/blog/onderhond/inline-block-vs-float
Thierry
# April 15, 2010 - 3:30 am
@ Niels:
“True to a certain extent, but with more differences than the buts and ifs shown in this article. Inline-block leaves white-space gaps”
I don’t think this issue would come into play in the case of a layout where there would be an “inline-block” following float(s).
“which (unless you tamper with the actual html) can’t be removed properly as far as I know”.
I read your article and I see that you reference a succession of elements styled as inline-block which is quite different. Besides tempering with the html (which imho is no big deal as this code would most likely be in an include), you could use the “word-spacing” property. Giving it a negative value (to be applied to the parent element) should close the gap between the elements.
Thanks for your feedback
Max
# April 14, 2010 - 1:04 am
Some good points in this article, however, I think that mentioning IE5 these days is a bit too much. Hasn’t this all been covered by Ed Eliot already?
Nicolas Gallagher
# April 14, 2010 - 1:39 am
Using a generic “clearfix” class couples declarations for modern browsers with declarations for IE despite their different rendering models.
If an element needs to clear its floats in modern browsers and you need to retain visible overflow (or prefer not to use overflow to contain the floats) then there is nothing stopping you from using :after to target the specific elements by their tag, class, or id. There is no need to add a new (presentational) class to the HTML or for any IE declarations to be coupled to the styles targeting modern browsers. Any requirements to trigger layout in IE can be handled completely separately and independently on a case-by-case basis in a conditional style sheet.
This gets around the most significant problem you highlighted.
Tony Aslett
# April 14, 2010 - 2:05 am
Nice to see the clearfix technique still getting discussed and used. It’s just about 6 years old now. http://csscreator.com/attributes/containedfloat.php
Thierry, thanks for taking the time to explain the issue and solution. Generally I try to avoid padding and margin on floated elements, that might be why, like the others I haven’t come across this issue.
Thierry
# April 15, 2010 - 3:36 am
Hi Tony,
Thanks for stopping by and thanks for this *really clever* solution.
Josh Kill
# April 14, 2010 - 3:49 am
Best way to clear (trust me, I’ve tried and tested them all):
overflow:auto; /*works on everything back to IE7*/
_height:1%; /*hack for IE6 support*/
Max
# April 15, 2010 - 12:58 am
Which also results in invalid CSS mark-up?
Thierry
# April 15, 2010 - 3:40 am
There are *many* ways, but I don’t think there is a best way.
It all depends on construct and requirement.
For example, overflow:auto could trigger scrollbars
Jonathan
# April 14, 2010 - 9:23 am
Amazing post Thierry, thank you very much!
I must admit that I (probably along with every other web developer I know) had no idea about block formatting contexts – I suppose the nitty gritty of the CSS specs is something we hardly ever need to worry about, CSS mostly just works so we never question why.
I’m someone who always goes for :after for my float clearing, partly because I enjoy the cleverness behind it, but also because I never understood why overflow should cause a float clearing effect. It seemed to be a random effect to me, nothing to do with overflow but now I know better.
I have often had problems with the overflow method when picking up work done by another developer, but now I will give it more consideration, especially if floats are behaving strangely in IE.
So thank you again. More posts like this please! Specs are quite often not the easiest things to read, so having someone give a good explanation like this is very welcome.
Thierry
# April 15, 2010 - 3:44 am
Hi Jonathan,
Yes, new block formatting contexts are a big deal when it comes to visual rendering, but in a good way. I find them very helpful when it comes to create layouts/grids.
See http://www.ez-css.org
Thanks for your feedback
Joachim
# April 14, 2010 - 11:45 am
Why not just put something like “” after floating elements. You could then style .clearfix with css accordingly like so:
.clearfix {
clear:both;
height:0px;
text-indent:-9999px;
font-size:0px;
}
As far as I know and if i get things right, this approach is…
1. semantically correct
2. valid
3. does what we need and
4. even recommended by the w3c.
Have a look at:
http://www.w3.org/TR/1999/REC-html401-19991224/struct/text.html#edef-BR
and
http://www.w3.org/TR/1999/REC-html401-19991224/present/graphics.html#adef-clear
Joachim
# April 14, 2010 - 12:01 pm
The markup in the doublequotes is <br class="clearfix" /> of course
Thierry
# April 15, 2010 - 4:08 am
Hi Joachim,
I’m not sure about the need for “text-indent” in that clearfix rule. Besides, if I recall, using BR may fail in IE6.
In any case, this technique goes against the idea we’re discussing here, which is about clearing/containing floats with *no* structural markup.
Thanks
Jordan Walker
# April 14, 2010 - 1:02 pm
That is something I have not considered, thanks for the article…good read.
bart
# April 14, 2010 - 2:12 pm
To make the IE and modern browsers look same you can:
.wrapper {
…
overflow:hidden;
_overflow:visible; /* IE6 */
_height:0; /* IE6 */
}
.mainContent {
padding-right:200px;
padding-left:200px;
*padding-bottom:1px; /* IE lt 8 */
*margin-bottom:-1px; /* IE lt 8 */
}
Can someone verify this? I tested in IE6, IE7, IE8, Firefox 3.6, Chrome 4.1.249.1045, Opera 10.51, Safari 4.0.3 (win). Are there any drawbacks to doing this?
bart
# April 14, 2010 - 2:23 pm
Also works fine with display:inline-block in the .wrapper
bart
# April 14, 2010 - 3:09 pm
For demo 4, you have to use negative margin-bottom of -13px on the .mainContent for IE lt 8.
Overall I think demo 2 is best since you can still use “normal” left and right margins on .mainContent. In demo 4 your margins have to be larger than the widths of the floating sidebars.
Thierry
# April 15, 2010 - 4:18 am
Hi Bart,
Using right/left padding on .mainContent is a technique I used to do *years* ago, but this creates weak construct as you cannot clear within that container.
“In demo 4 your margins have to be larger than the widths of the floating sidebars.”
This is by specs (nothing wrong with that). This block formatting context has its border box (*not* its margin box) fit between the two floats. This means that implicit margins are created by the browser. These margin values are equal to the floats’ margin box.
Usually, with such contructs we would apply margin to the floats, not to the block formatting context.
Thanks
bart
# April 16, 2010 - 12:11 am
Very good point about not being able to clear floats in .mainContent in demo 2.
Have you seen http://oocss.org/grids_docs.html? It’s based on formatting context created by overflow:hidden in content adjacent to floats.
Thanks again for a great explanation and sharing your knowledge. I’ll definitely have to check out EZ-CSS.
Thierry Koblentz
# April 20, 2010 - 3:36 pm
@ Bart
Yes I know about oocss. I believe I’m one of the commenters on the page you link to ;).
Please do *not* follow this link for now though because it is flagged by Kaspersky. I’ll contact Nicole.
Russell Heimlich
# April 14, 2010 - 2:33 pm
This article seems overly long and complicated for the simple advice of “Just use overflowauto;height:100% instead”
Here is everything you need to know about clearing floats -> http://www.russellheimlich.com/frontend-tips/clearing-floats.htm
If overflow:auto won’t work for your situation (like absolute positioning an element beyond the boundaries of a container) then use clearfix instead.
Thierry Koblentz
# April 14, 2010 - 4:26 pm
Hi Russell,
“If overflow:auto won’t work for your situation [...] then use clearfix instead.”
I think a better approach would be to use a different block formatting context trigger (i.e., display:inline-block). That way you do not style things differently across browsers.
Dan
# June 19, 2010 - 10:26 pm
Just tried your method and now my header has a scrollbar. I also can’t use overflow:hidden for various other reasons. That’s hardly everything you need to know about clearing floats.
Frances de Waal
# April 14, 2010 - 3:49 pm
What if I want #maincontent to strech with #floatme. Then the same solution won’t work. Do you agree or did I miss something?
Frances de Waal
# April 14, 2010 - 8:19 pm
Aah… I had to take another look but now I see… nice, very nice!
Ingo Chao
# April 14, 2010 - 6:10 pm
Looking for a follow-up article on overflow:hidden and why it is still called a “simple solution” in spite of its adverse effects. There is no CSS 2.1 property that triggers a block-formatting context that does only that: creating a bfc without unwanted side effects.
Thierry
# April 15, 2010 - 4:35 am
Hi Ingo,
I agree. As I say in one of the comments above, there is no magic bullet. For sure “hasLayout” looks really sexy when we see that all bfc triggers come with some side effects.
As a side note, there is no perfect CSS solution, but there is a HTML one… Far from being semantic (so not perfect either), but it does the job well:
http://www.ez-css.org/rapid_prototyping
Thanks for stopping by
Semblance
# April 14, 2010 - 9:06 pm
Hi Thierry. Thank you for you post. This sort of thing confused me, that I end up doing all sorts of unnecessary code to make thing look right across browsers. Your post along with everyone’s input in comments has cleared up a lot of things and will spare me valuable time and pulling my hair out!
Thierry
# April 15, 2010 - 4:25 am
Hi Semblance,
I’m glad you find this article and its comments useful.
Thanks for your feedback
Antonio Fernandes
# April 15, 2010 - 12:58 am
Awesome and Insightful. I learned something i didnt know about IE thanks.
Paweł P.
# April 15, 2010 - 10:20 am
@Thierry – Good work and good
discussion. Best regards!
kelly
# April 18, 2010 - 1:04 pm
very thoughtful stuff…..well written article
Samuel Santos
# April 20, 2010 - 11:43 pm
It is sometimes hard to detect floating errors. I usually use a CSS Float jQuery plugin to find them.
Wolf
# April 27, 2010 - 5:44 pm
This article is misguided.
If your main wrapper has overflow: hidden;, what if you have any dropdowns sticking out of the main wrapper? A popover or megadropdown like in most modern user interfaces?
O yes, these get cut off, and there’s no way to fix it without removing the overflow: hidden.
People saying you have to use overflow: scroll end up with scrollbars.
In demo 4, the the 3 columns should float to the left with defined widths. The wrapper gets clearfix using the :after method for modern browsers and zoom: 1 or display: inline-block so it gains layout in IE6 (See: http://www.satzansatz.de/cssd/onhavinglayout.html )
Basically any wrapper containing floats has to have clearfix applied, and any direct child of that wrapper should float. So in the case of a wrapper div with 3 columns, the colums float; the contents of the colums do not.
Thierry Koblentz
# April 28, 2010 - 12:27 am
Hi Wolf,
What you’re saying about content being cut-off has already been addressed in previous comments.
Also, your suggestion about demo #4 would fail to create a fluid layout as these sidebars have their width set in pixels.
“Basically any wrapper containing floats has to have clearfix applied”
Good luck with that! ;)
Bart - Css Newbie
# April 29, 2010 - 6:19 am
Great post! I have a question though.
Consider this markup:
…
Shown
Hidden
…
And Css:
#wrap {
margin: 10px;
padding: 10px;
border: 1px solid #ccc;
position: relative;
overflow: hidden;
}
#wrap div.shown {
float: left;
height: 100px;
width: 100px;
border: 1px solid #ccc;
}
#wrap div.hidden {
border: 1px solid #ccc;
display: none;
height: 100px;
width: 100px;
position: absolute;
top: 110px;
left: 10px;
}
#wrap:hover div.hidden {
display: block;
}
What basically happens is when you hover over the “wrap” element, the child “hidden” will show (Supposed to be). Using the overflow approach, unfortunately it is sort of being cut-off. Sir Mal pointed this out and I didn’t quite get the solution using “display:inline” and “width: of some sort” (No really sure). Perhaps a concrete example based on the code I’ve given will enlighten me more. Regards.
Thierry Koblentz
# May 1, 2010 - 3:10 pm
Hi Bart,
As you can see your markup doesn’t show. Could you publish a test case and post the URL?
You can also email me everything if you wish (my first name @tjkdesign.com)
Thanks
Marc watts
# June 27, 2010 - 10:48 am
The best way to use a clearfix can be found at best clearfix ever. It doesn’t use class names to fix the problem but an automatic solution that should be applied to all block level elements except for the p and footer elements.
Thierry Koblentz
# July 7, 2010 - 12:29 am
@Marc Watts
As I told you on http://perishablepress.com/press/2009/12/06/new-clearfix-hack/ your “technique” is a really bad solution. It can only create more issues than it solves.