A new micro clearfix hack

The clearfix hack is a popular way to contain floats without resorting to using presentational markup. This article presents an update to the clearfix method that further reduces the amount of CSS required.

Demo: Micro clearfix hack

Known support: Firefox 3.5+, Safari 4+, Chrome, Opera 9+, IE 6+

The “micro clearfix” method is suitable for modern browsers and builds upon Thierry Koblentz’s “clearfix reloaded”, which introduced the use of both the :before and :after pseudo-elements.

Here is the updated code (I’ve used a shorter class name too):

/**
 * For modern browsers
 * 1. The space content is one way to avoid an Opera bug when the
 *    contenteditable attribute is included anywhere else in the document.
 *    Otherwise it causes space to appear at the top and bottom of elements
 *    that are clearfixed.
 * 2. The use of `table` rather than `block` is only necessary if using
 *    `:before` to contain the top-margins of child elements.
 */
.cf:before,
.cf:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.cf:after {
    clear: both;
}

/**
 * For IE 6/7 only
 * Include this rule to trigger hasLayout and contain floats.
 */
.cf {
    *zoom: 1;
}

This “micro clearfix” generates pseudo-elements and sets their display to table. This creates an anonymous table-cell and a new block formatting context that means the :before pseudo-element prevents top-margin collapse. The :after pseudo-element is used to clear the floats. As a result, there is no need to hide any generated content and the total amount of code needed is reduced.

Including the :before selector is not necessary to clear the floats, but it prevents top-margins from collapsing in modern browsers. This has two benefits:

  1. It ensures visual consistency with other float containment techniques that create a new block formatting context, e.g., overflow:hidden
  2. It ensures visual consistency with IE 6/7 when zoom:1 is applied.

N.B.: There are circumstances in which IE 6/7 will not contain the bottom margins of floats within a new block formatting context. Further details can be found here: Better float containment in IE using CSS expressions.

The use of content:" " (note the space in the content string) avoids an Opera bug that creates space around clearfixed elements if the contenteditable attribute is also present somewhere in the HTML. Thanks to Sergio Cerrutti for spotting this fix. An alternative fix is to use font:0/0 a.

Legacy Firefox

Firefox < 3.5 will benefit from using Thierry’s method with the addition of visibility:hidden to hide the inserted character. This is because legacy versions of Firefox need content:"." to avoid extra space appearing between the body and its first child element, in certain circumstances (e.g., jsfiddle.net/necolas/K538S/.)

Alternative float-containment methods that create a new block formatting context, such as applying overflow:hidden or display:inline-block to the container element, will also avoid this behaviour in legacy versions of Firefox.

Reply on Twitter Retweet on Twitter Favorite on Twitter

57 comments

#

Darren Armstrong says…

Nice work, very concise! I’ll be using this in my next build. Will report any bugs. Thanks.

#

Jatin says…

It really works, Brilliant.

#

Thomas says…

Really nice solution !
I will try to use it in my next project too ;-)

Thanks for sharing,
Thomas.

#

Colin Richardson says…

Aha! Good stuff, I shall also give this a bash and see how it goes. While overflow:hidden; serves me well 90% of the time, there is occasional hoop-jumping when it comes to clipping what should not be clipped.

#

Benjamin says…

For the non-IE code I’d suggest to use the standard pseudo-element notation ::after.

#

Nicolas says…

@Benjamin: That post-CSS2.1 notation is not supported in IE 8.

#

Dan Cowley says…

This has literally come straight off your site and into a current project, great solution to this issue and also eliminates the downsides of using overflow: hidden!

#

Catalin Red says…

Nicolas, this clearfix looks very clean.

Thanks for sharing this solution and I’m looking forward to use it in my projects!

For the demo page, I’d suggest you to avoid the “double margin” bug (IE6). This way the clearfix method will be more visible when testing the demo example on IE6.

#

Nicolas says…

@Catalin: Thank you for bringing that to my attention! I’d overlooked it following a change to the margins used in the demo. It’s now been fixed.

#

Edmundo Junior says…

Oh so simple and so beautiful done!

#

Mark Simpson says…

Thank you Nicolas, I love this!

If you’re going to shorten from .clearfix or .clear to .cf, you might also consider dropping three unnecessary semi-colons. Every bit counts :)

#

Vaibhav Gupta says…

a brilliant work for clearfix..
I much appreciate..

#

Wouter Beeftink says…

@Mark Simpson: Unless I’m wrong, the main point of this script is removing the need to have an extra element within your HTML on which you can apply clear: both;, not save a couple of bytes.

@Nicolas: Thanks, I’m going to give it a shot in my next project. I wonder how you found out about the IE6 and 7 fix ;-)

#

Dr.Death says…

I’ll use this next time!

#

suprMax says…

Pretty nifty! Thanks!

#

Martin Bean says…

Great stuff! I shall look forward to using this in upcoming new projects.

#

Matthew Lein says…

Am I the only one that is seeing bottom margin collapse in IE7?

Are my IE7s F-ed?

I checked on 2 VMs, XP and Vista. I’m sure you guys tested this thoroughly…anyone else?

#

Nicolas says…

@Matthew Lein: No you’re not the only one. Thanks for bringing this up, it has exposed some interesting details.

The original demo used left- and right-floated elements (of equal height). In these circumstances, it seems that IE 6/7 will not collapse the bottom margin of the right-floated element.

However, I later simplifed the demo and only used left-floated elements, not expecting it to make a difference. This has exposed an inconsistency in IE 6/7. If the child elements are only left-floated then the bottom margin disappears and there is no obvious way to avoid this. I’m not sure if this has been documented before; I haven’t come across it. Previous clearfix articles and demos, including those by Position Is Everything and Thierry, made no mention of it either.

IE 6 gets even crazier. Under specific circumstances, IE 6 won’t collapse bottom margins when there are only left-floated children. But for that to happen, there has to be 2px or less of space between the last left-floated child and the right-most edge of the container. That “space” is measured from beyond the element’s right-margin. If you look at the demo in IE 6 you will notice that the bottom margins are not collapsed.

In short, this kind of behaviour suggests that it might actually be impossible to ensure that margin-collapsing is consistent across browsers while IE 6/7 are still in use.

There is also an inconsistency between modern browsers when using the original “micro clearfix” code. Under another set of circumstances, Firefox will leave a space between the top of the body and the first child element. This seems to happen when the first element of the body contains floats but has no content (or new block formatting context) between the floats and their parent. It is not a problem with Thierry’s method and is also avoided when using clearing methods that create a new block formatting context.

I hope to put together test-cases to demonstrate these behaviours. An update is in order.

#

Thierry says…

Versions of Firefox prior to Firefox 3.5 will benefit from using Thierry’s method with the addition of visibility:hidden to hide the inserted character.

Actually, there should be no need to add visibility:hidden as it is for this reason (to hide the “.”) that my method includes height: 0; and overflow: hidden;

As a side note, there is a known issue in IE6/7 with *default* margins. In these browsers, elements that have a layout do not contain default vertical margins (they do prevent *explicit* margins from collapsing though). See: http://www.css-101.org/collapsing-margin/03.php

Great to see you working on pushing the envelop. I’m really looking forward to the *super micro* clearfix method:

.cf:before,
.cf:after {
    content:"";
    display:table;
}

.cf:after {
    clear:both;
}

:-)

#

Nicolas says…

@Thierry: I also thought that including overflow:hidden in the clearfix code would hide the generated content, but my tests in Firefox 2.0 – 3.0 had the “.” showing until visibility:hidden was included.

Thanks for the heads-up about the default margin bug. Didn’t know about that one!

#

CSS Webstandard-Blog says…

Nice and smart CSS3 solution for clearing. Thx for sharing Nicolas! you already checked that at the new IE10 Pre-Beta?

#

neil says…

Am I missing something or is this redundant since using overflow:hidden does the same thing?

#

Nicolas says…

@Neil: Using overflow:hidden is an alternative method of containing floats that creates a new block formatting context (see the last paragraph of the post). It has different drawbacks; both methods are worth knowing and using when most appropriate.

#

Bob Crosbee says…

Here’s another thought. Define the columns as table cells via css. This will stop us from using a clearfix hack.

Now before you start yelling about tables, using the table value of the display property shows how something should look in your browser. No semantic meaning so it’s perfectly fine, actually a much better solution to this problem.

.container {
     display: table;
}
.row {
     display: table-row;
}
.cell {
     display: table-cell;
     width: 10px;
     height: 10px;
     border: 1px solid red;
}
#

Nicolas says…

@Bob Crosbee: The problem with using table display types is that you become dependent on source order, you are often left emulating table markup, and they are not supported by IE 6/7.

#

Shane Hudson says…

Impressive, really neat… before playing about with the example I did not believe it would actually work. Great find!

#

Optimise Web says…

Nice, thanks. I see it has been implemented into HTML5 Boilerplate too.

#

Plechazunga says…

This is fantastic. Now that clients are making me put grotesque amounts of box-shadow on everything, this certainly beats overflow:hidden.

Thanks! :)

#

Elements Aside says…

I’ve been using this in my latest projects, works great. However, as Dan Cederholm has pointed out, using the class name “group” is more semantic than using “cf”.

#

Matt says…

Very nice indeed. Am going to add this to a project I’m working on. Will post up with any bugs if I run into ‘em. Elegant solution.

#

Timothy Warren says…

I don’t see why I need this if I’ve got display:inline-block, and zoom:1; display:inline for IE 6/7.

#

Nicolas says…

@Elements Aside: I don’t think using a class like “group” is any better. IMO, it’s worse because it is vague and obfuscates the very specific purpose of the class. Just because some content is grouped doesn’t mean that there are any floats that need to be contained. And very common components (like floated-image + text) that require float containment could only be tenuously described as “groups”.

@Timothy Warren: display:inline-block results in other effects that are distinct from the float containing that is desired. White-space in the code can affect the rendering and the width of the element can be affected.

#

Peter says…

This is an excellent clearfix hack. Very tidy and semantic. Good work!

#

Ryan says…

Can someone explain why the :after is only cleared and not that and the :before?

TAI

#

Ian Storm Taylor says…

Would I be right to assume that if I have no interest in IE6 or IE7 support, the following would do me fine:

.cf:after { content:""; display:table; clear:both; }

Since I don’t need to support the zoom:1, couldn’t I also just have top-margins collapse successfully everywhere then and have this uber micro version?

#

Martin Bavio says…

Ok, I need to know this. I’m reading here about the “downsides” of overflow:hidden technique. Can somebody explain me the downsides of it? Thanks!

#

Ryan says…

@Martin It will clip off elements that flow outside the container, absolute positioned elements for example.

#

Nicolas says…

@Ian Yeah, that’s all you’d need.

@Martin What Ryan said. Another example is box-shadow gets clipped.

#

Rhys Burnie says…

Fantastic! Here’s a simple sass mixin if anyone is interested:

@mixin clearfix-micro() {
    & {
        *zoom: 1;
    }
    &:before,
    &:after {
        content: "";
        display: table;
    }
    &:after {
        clear: both;
    }
}

Usage:

.whatever {
     @include clearfix-micro();
}
#

Mark says…

Looks great, and I’ve used it on one site so far. However, I don’t quite see how this is less code than the other clearfix method:

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

That is just one line, if you format your CSS syntax as so. And the micro fix requires at least three lines of CSS for the three different rules.

#

Nicolas says…

@Mark It’s explained in the article:

Including the :before selector is not necessary to clear the floats, but it prevents top-margins from collapsing in modern browsers.

If you don’t need this consistency, then you don’t need the two separate :before, :after and :after rules. The old piece of clearfix code you’ve included is also missing the rule required to trigger a new block formatting context in IE6/7.

#

Bob FiveThousand says…

Ahhhh! Lifesaver!

The old PIE method was failing me in FireFox 8+. An bunch of reasearch told me why and a little more led me here.

So thanks! :-)

#

Richard A. Allen says…

Just finished switching from Perishable Press New Clearfix and I confirm that it works well on Drupal 7. While the New Clearfix worked well for Firefox, I was having major consistency issues in IE6 and IE7, and other minor issues in other browsers. Congratulations, I present the Seal of Approval to the Micro Clearfix !

#

Thomas says…

This is really useful :) Just a question, do we have to use :after instead of ::after?

Thanks for sharing this snippet!

#

Nicolas says…

@Thomas Yes, because IE8 doesn’t support the ::after notation.

#

Kzqai says…

Pretty weird that we still need patches like this to wrangle browsers into allowing cleaner layouts. I wonder if in there are any css3 proposals for alternatives to clearfix with floats. But I guess it wouldn’t matter for the next 20 or so years as legacy browsers were phased out anyway.

I guess the layout proposal is our next best hope?

#

Max says…

In Opera 11.62 if on page we have any div.clearfix and any <div contenteditable="true">, the blocks with clearfix have additional height.

#

Nicolas says…

@Max: That’s a strange Opera bug (example: http://jsfiddle.net/ZSy3N/1/). You can get around it by adding font:0/0 a to the clearfix code generating pseudo-elements. This will prevent Opera from showing the extra space for the pseudo-element content. No other browser I tested had this problem.

.cf:before,
.cf:after {
    content: "";
    display: table;
    font: 0/0 a;
}

...
#

Sergio Cerrutti says…

Hey Nicolas,

The font fix is working ok, but there’s another way to avoid this bug, using a white-space inside the content attribute:

.cf:before,
.cf:after {
    content: " ";
    display: table;
}
#

Nicolas says…

Thanks Sergio, good spot! I’ve updated the post to use a space in the content string and clarify a few other things. IIRC, I originally removed the space to avoid the potential for it to cause space to appear in the UI. But this might have been for legacy browsers that are now so rare as to be unimportant. I’ll double check.

#

Tokimon says…

Thanks Nicolas for this simple way to make elements wrap floating elements. It’s pretty neat.

I have one question however:

If you are generating the same code for both the :before and the :after element, why not just apply clear: both; to the both of them, instead of singling out :after as the only one who gets that statement? Would it interfere with something? Because by combining it into one statement, you are actually making the code even simpler:

.cf:before,
.cf:after {
    content: " ";
    display: table;
    clear: both;
}

.cf { *zoom: 1; }
#

Jeremy Boggs says…

I’ve run into a slight issue in using this method. I have a div floated left, with a fixed width, and then a second div with a left margin slightly wider than the width of the left column (no width). If I apply the clearfix to any elements inside the second column, they also clear the left-floated div.

Example: http://jsfiddle.net/kKtVu/

But applying overflow:hidden; to my second column, for example, seems to fix this.

Example: http://jsfiddle.net/kKtVu/1/

I was somewhat surprised to see that the :after pseudo-element didn’t honor its ancestor’s left margin, or inherit the width of element to which it was attached. I’m curious if anyone else has run into this, and if there might be a better solution than the one I added in my second example.

#

Nicolas says…

@Tokimon If you apply clear:both to :before then you end up with the element (with the cf class) clearing preceding floats.

@Jeremy That issue is true of all clearfix methods due to the use of clear:both. To avoid it clearing floats outside of the element it is applied to, you need to create a new block formatting context. One way to do that is to use overflow:hidden (as in your example). Other properties that trigger a new block formatting context include float:left|right, e.g., http://jsfiddle.net/kKtVu/2/ or display:table-cell, e.g., http://jsfiddle.net/kKtVu/3/. Each property has its own drawbacks.

#

Tom Kenny says…

There’s something really nice about seeing this used everywhere, from H5BP to Bourbon. Great work! You make web design that much easier.

#

@Jonic says…

If you use Sass placeholders you can save even more code. Instead of declaring the clearfix as a mixin, declare it as a placeholder like this:

%clearfix-micro {
    &:before,
    &:after {
        content: " ";
        display: table;
    }
    &:after {
        clear: both;
    }
}

And then use it like this:

.foo {
    @extend %clearfix-micro;

    /* Other styles for .foo */
}

.bar {
     @extend %clearfix-micro;

     /* Other styles for .foo */
}

.baz {
     @extend %clearfix-micro;

     /* Other styles for .foo */
}

Note the @extend and the % to denote a placeholder. That will then compile to this:

.foo,
.bar,
.baz {
    *zoom: 1;
}

.foo:before,
.bar:before,
.baz:before,
.foo:after,
.bar:after,
.baz:after {
  content: " ";
  display: table;
}

.foo:after,
.bar:after,
.baz:after {
  clear: both;
}

.foo {
    /* Other styles for .foo */
}

.bar {
     /* Other styles for .foo */
}

.baz {
     /* Other styles for .foo */
}

So everything that uses your clearfix rules are compiled and output in that one placeholder selector, rather than the CSS rules being included inside each selector.

Using Sass placeholders can dramatically cut down the amount of CSS repeated in a stylesheet. You can read more about them on Sass-contributor Chris Eppstein’s release notes for this feature.

#

Jeremy Boggs says…

@Nicolas Turns out I can solve my issue by adding width: 100%; to the clearfix rule for :before and :after pseudo elements, and get rid of rule with clear:both altogether.

.cf:before,
.cf:after {
content: ” “;
display:table;
width:100%;
}

.cf {
*zoom:1;
}

See the JsFiddle. This seems to have the advantage of having the pseudo elements span the entire width of their parent and effectively clear anything above and below them. Haven’t run into any issues with this yet, so I’m curious what you think or if you foresee any issues with this approach.

Comment on this post

Please wrap code fragments in <code> tags, wrap blocks of code in <pre><code>, and use JsFiddle to post working examples.