company-logo

Developer's Notebook: Forward-thinking CSS float-clearing

The art of float-clearing – getting containers to honor the height of floated elements inside of them – has slowly evolved over the past several years as Safari has taken over many Mac desktops, IE5/Mac has atrophied, IE7 has slowly caught on, and our use of CSS filters has improved. I’d like to share a slight variation on the state of the art that I believe makes for much cleaner markup. But first, a little background.

How we got here

Several years ago, Tony Aslett of csscreator.com convinced us to stop using clearing our floats using this sort of junk markup:

<div id="container">
   <div id="rail" style="float: left;"></div>
   <div id="content" style="float: left;"></div>
   <br style="clear: both; height: 0; visibility: hidden;">
</div>

His solution, popularized on Position is Everything, convinced us to use pure CSS to solve the problem:

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

.clearfix {display: inline-block;}

/* Hides from IE-mac \*/
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide from IE-mac */

<div id="container" class="clearfix">
    <div id="rail" style="float: left;"></div>
    <div id="content" style="float: left;"></div>
</div>

The advantage, of course, was that you didn’t have to litter your markup with extra <br /> tags that would eventually become totally useless once the state of the art changed.

Where we are now

For sites that have dropped support of IE5/Mac and adopted support of IE7, the recent concensus on float-clearing has been something like this (using the same markup as above):

/* float clearing for IE6 */
* html .clearfix{
  height: 1%;
  overflow: visible;
}

/* float clearing for IE7 */
*+html .clearfix{
  min-height: 1%;
}

/* float clearing for everyone else */
.clearfix:after{
  clear: both;
  content: ".";
  display: block;
  height: 0;
  visibility: hidden;
}

And now, a slight refinement

Which leads me to a technique used at Orbitz, my previous employer, to apply the same methodology with even less impact on the markup itself. Instead of declaring a single clearfix class and then applying it to countless containers inside their XHTML, the Orbitz UI team uses a grocery list of CSS selectors, like this:

/* float clearing for IE6 */
* html #container,
* html .classThatNeedsToBeCleared,
* html div.anotherClassThatNeedsToBeCleared,
* html #someDiv .someClass .yetAnotherClassThatNeedsToBeCleared{
  height: 1%;
  overflow: visible;
}

/* float clearing for IE7 */
*+html #container,
*+html .classThatNeedsToBeCleared,
*+html div.anotherClassThatNeedsToBeCleared,
*+html #someDiv .someClass .yetAnotherClassThatNeedsToBeCleared{
  min-height: 1%;
}

/* float clearing for everyone else */
#container:after,
.classThatNeedsToBeCleared:after,
div.anotherClassThatNeedsToBeCleared:after,
#someDiv .someClass .yetAnotherClassThatNeedsToBeCleared:after{
  clear: both;
  content: ".";
  display: block;
  height: 0;
  visibility: hidden;
}

<div id="container">
    <div id="rail" style="float: left;"></div>
    <div id="content" style="float: left;"></div>
</div>

The idea here, of course, is that each time you have another container that needs to be cleared, you add browser-specific selectors for it to each of the three blocks above. Suddenly, there’s no need to apply a utility class to a zillion different nodes in your HTML. Instead, you apply the same CSS rules to a bunch of atomic CSS selectors. Voila: float-clearing with absolutely no impact on markup. Presto: a solution completely centralized in a single block of CSS code, so that it can be changed in one place as the browser landscape evolves.

(Props to Gena Wilson, Orbitz’s CSS headmistress extraordinaire, for constantly synthesizing elegant solutions like this one.)

Final side note: As long as folks are going to keep griping about missing items from their CSS wish list, could we please just eliminate the need to clear floats altogether? I know that the need to clear floats isn’t actually a bug, according to the WC3, but it should be. I can’t think of a single time I’ve ever _not_ needed to clear my floats. Can you? Tell me in the comments.

  1. T.J. Reply

    I think that both of these methods for clearing floated divs is sloppy. Whether in your HTML or CSS, your still going to have sloppy code in the end run. I used to use the .clearfix method mentioned above in your article, but still ran into the problem of having to either add that style to multiple classes or to make some significant layout changes to the website (or use inline float-clearing objects).

    I know semantically speaking your not supposed to have any extra HTML than is required, as everyone says CSS. Personally I now use an extra div around floated content with it’s only style definition (in the CSS) being a padding declaration.

    At the end of the day, my divs can expand and contract at will with no overlap issues, my html and css validate, and I can go on with my life not having to google for that annoying IE clearfix hack.

  2. Ryan Doherty Reply

    What about using

    floatedElementClassName {
    zoom:1;
    }

    for IE (forces hasLayout property) and

    floatedElementClassName:after {
    content:”.”;
    display:block;
    clear:both;
    height:0;
    width:0;
    line-height:0;
    visibility:hidden;
    }

    For Firefox, Opera and Safari.

    No extra code in your html and just 1 extra declaration in your css. Works quite well for me!

  3. Ryan Doherty Reply

    Ugh, those declarations should be for the floated elements container, not the element itself.

  4. Craig Francis Reply

    I thought the method used now was:

    —–

    [div id="wrapper"]
    [div id="nav"][/div]
    [div id="content"][/div]
    [/div]

    —–

    #nav,
    #content {
    float: left;
    }

    #wrapper {
    overflow: auto; /* For FF, Safari, Opera, etc */
    width: 100%; /* For IE5, IE5.5, IE6, IE7 */
    }

    —–

    The basis is that the “good” browsers use the overflow:auto to contain the floated elements… but for IE, we use one of its bugs, whereby it contains the child floats when it has a width set.

    I have seen two issues with this technique though…

    1) Sometimes the design does not allow the width to be 100%, px, em etc… for example if you have padding on the fixed width container, the width gets incorrectly calculated (box model issue).

    2) If you have a link right against the edge of the floated element, then when you select that link (click, or tab focus), in FireFox it can cause the overflow scrollbars to appear due to the “selected” border it uses… sometimes you can to add a 1px margin to the link, which creates a small space for that border to appear.

  5. marcos Reply

    Me thinks it’s a very ugly solution when this is cleaner:

    #container {overflow:hidden;}

    that for ‘real’ browsers.

    Add zoom:1, _height:1%, width:(something) to trigger haslayout and you have it for ie6 and up (I usually have a separate stylesheet and conditional comments for that, so _height can be just height)

    Needless to say that if #container already has a width value due to it’s own nature all the ie stuff is not needed.

    Cheers from Spain

  6. Aaron Belafonte Reply

    quote: “I can’t think of a single time I’ve ever _not_ needed to clear my floats. Can you? Tell me in the comments.”

    If you’ve ever floated an image next to a block of text, then you’ve witnessed an instance where you did not have to clear your floats.

    Remember, that’s what the originally conceived context of floated elements was intended to address.

    see this article by eric meyer from 2003
    http://www.complexspiral.com/publications/containing-floats

  7. Hans Peter Nielsen Reply

    “If you’ve ever floated an image next to a block of text, then you’ve witnessed an instance where you did not have to clear your floats.”

    If your text content is dynamic and/or the width of the text column is dynamic, you cannot be sure the text will extend the height of the image without clearing the image float.
    If you want more than one image in the text paragraph, the same applies.

    So in my opinion you need to clear an image float in text paragraphs more often than not :)

  8. Aeonax Reply

    So… you’ve unlittered the markup and littered the css. Nice!

  9. Gena Wilson Reply

    A couple clarifications on why this approach worked for us–

    We were building a site that needed to be as fully skinnable/customizable as possible without needing changes to markup (but was allowed unlimited CSS differences via independent stylesheets). Needing to enclose floated elements vs. not wanting to do so was not a good enough reason for changing the markup. And in the interest of code transparency it was important to not have something like “clearfix” ever overwritten to not enclose floats. It would be like having a class of “pinkBorder” that’s set to be green in some implementations — uncool, especially in a multiple developer environment.

    We also knew that designers sometimes like to employ the technique where graphics or text extend out of their parent container (but semantically, still belong inside it). (Like a “New/Improved” graphic overlapping the corner of an element.) For those cases, we needed overflow: hidden not to cut off that escaping content, and overflow: auto not to force scrollbars on it (even though in many other circumstances either would be more elegant). And don’t even get me started on overflow: auto + a floated parent + Safari 2.

    Lastly, we wanted our CSS to validate, which prevented the use of proprietary IE properties like “zoom” or things like the underscore hack.

    We went with the above technique for those reasons; it’s most flexible for what we needed.

    Finally, while this problem is often discussed in terms of float clearing, it may be useful to clarify that the code above causes parent elements to *enclose* their floated children. If browsers and designs supported it, it could be just as effective, and probably more transparent, to select the first subsequent sibling of div.containerWithFloats and add the appropriate clear (left/both/right) rule. (Because this technique describes how to make div.containerWithFloats, due to its float enclosing, have subsequent elements no longer need to clear it.)

  10. Brian Dillard Reply

    I deliberately stayed out of the comments fray on this one, but I’m grateful to my former colleage Gena for stepping in to explain more of the whys and wherefores behind this solution – something I should have done better in my original post.

    My problem with a lot of CSS how-tos is they assume a small pool of developers, a tightly controlled codebase, and a relatively static site. In the real world, many of us work on huge sites maintained by global development teams, which requires defensive coding techniques. These apps must be skinnable – the same markup powering multiple white-labelled instances, sometimes on a variety of platforms (mobile/browser/etc.). They also rely on templating systems that may compose any arbitrary set of modules into pages; the CSS mustn’t break as a result of any specific configuration.

    The techniques that work for a mostly static, content-based site must be adapted for a complex webapp with multiple white-labelled instances. Thanks again to Gena for helping me illuminate why this particular solution worked well for one particular such app.

  11. presell Reply

    Thanks for this one …

  12. jethro Reply

    There just needs to be an extra property in CSS.

    Something like
    clear-children: clear/none;

    In all honesty should be set to clear by default. There have been times when I didn’t want to clearfix, but they’re rare enough that it shouldn’t be the norm. Although, float wasn’t designed for what we’re using it for. There really needs to be an alternative to float. I’m not terribly excited about the CSS3 Layout but it may be the way to go.

  13. Pingback: Pathfinder Development » What does your CSS Swiss Army knife look like?

  14. corroded Reply

    “I know that the need to clear floats isn’t actually a bug, according to the WC3, but it should be. I can’t think of a single time I’ve ever _not_ needed to clear my floats. Can you? Tell me in the comments.”

    QFT

    sadly i still use the old br class=”clear” routine :( it’s the easiest to remember and works for all browsers

Leave a Reply

*

captcha *