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.