May 10, 2009

Clearing floats with no clearfix

Oh, floats. Every web designer have worked with them. Floats let you rearrange the flow of elements. They're powerful, they're useful, they're... painly buggy on old browsers, I know. But they're one of the CSS2 most used properties, so they deserve some respect.

Let's make some fun with floats. We will design a simple menu from nothing more than pure HTML tags and some CSS magic.

<ul>
   <h2>Menu</h2>
   <li><a href="#">Option 1</a></li>
   <li><a href="#">Option 2</a></li>
   <li><a href="#">Option 3</a></li>
</ul>

Then we add some style

ul {
  list-style:none;
  margin:0;
  padding:0;
}
h2 {
  background:#369;
  color:#9CF;
}
li { background:#69C; }
a {
  color:#CFF;
  text-decoration:none;
}
a:hover { color:#FFF; }
li, h2 {
  float:left;
  font-size:12pt;
  height:2ex;
  margin:0;
  padding:0.5em;
}

South of the border

Wow, that was a nice improvement, with no HTML markup addition at all. Great! Now that I'm thinking, this <ul> would look even better with a border. Let's do it!

ul { border:2px solid #9CF; }

Oops! That was not what we intended at all!

With some of its children floating around, the <ul> has no idea of its own dimensions and ends like a 0px box. With a nice border, yeah, but kinda useless.

Float the problem

Let's try something. We can float also our little <ul> to tell it to cover all it's children extent

ul { float:left; }

But now the problem bubbles up one level. The parent node of the <ul> isn't aware of the height of it's own content, and thus, does not render correctly. Well, best said, it doesn't render as we would.

.container {
  background:#47A;
  padding:1em;
}

We surely can put a float:left in the container and go up again and again until floating left the <body> tag, but I don't think that's a good idea. Let's think deeper.

Clearing

More knowledgeable people thought the same and began to add some additional mark-up to do the clearing with clear: both. Something on those lines did the trick:

<div class="container">
   <ul>
      <h2>Menu</h2>
      <li><a href="#">Option 1</a></li>
      <li><a href="#">Option 2</a></li>
      <li><a href="#">Option 3</a></li>
   </ul>
   <div style="clear:both"></div>
</div>

Well, yeah, it does what we want, but... Hey, you're adding new markup to the HTML. You're polluting our beloved WWW with non-semantical inline-styled tags. Well, it can be done without inlined style, but the most important here is that you are mixing content with style. And mixing things is not always a great idea. Do you remember Diet Coke and Mentos?

Soon the WWW was a field infected with "clearbothitis", since it seemed no one could live without floats and no other solution arose.

Clearfix

Then even more knowledgeable people came with a CSS2 full equip solution. Introducing clearfix!

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

Of course, with some tons of additional hacks for it to work in some applications. Nice!! Now you only have to put some classes to call the div to order.

<div class="container clearfix">
   <ul>
      <h2>Menu
      <li><a href="#">Option 1</a></li>
      <li><a href="#">Option 2</a></li>
      <li><a href="#">Option 3</a></li>
   </ul>
</div>

And our example turns into:

IE users could experiment strange behaviour viewing these examples. But, hey, you already knew that, didn't you? Go download a decent browser, you Neanderthal!

Yes! This is what we intended. Now nearly every site has it's own clearfix derivative implementation. It's pretty neat, isn't it?

Clearfix drawbacks

Well, yeah, I must admidt it. But, despite me not being a guru, this fix has, for me, some problems:

  • Old non-CSS2-compliant browsers can't show it. "Yes", I hear you say, " but they're legacy, you can't support them 'til the end of time". Sure not, I know, but even now there are millions of users browsing the WWW with old browsers. Would you be the one ignoring them? Me neither.
  • Well, have I said this needs tons of non-edulcorated CSS hacks in order to work in those 'exploring tools' I mentioned early? I mean IE6 and IE7 with their "hasLayout" neverending stories, of course...
  • I can't find the evolution between this and the previous one. You used CSS2? Sure you're a modern web designer! But you're committing HTML4 crimes, because you've polluted your HTML nonetheless! This is not a step forward nor backwards. Is a step aside, in the better case.

Conclusion and overflow

I think my point of view is clear: Markup is for content. There's no room for class="clearfix" as there is no room for class="blue-left-floating-column-80px-width". But every now and then I had to eat my words and thoughts and points of view (and some other non-gratefully things) and admit there is no other way to do the right thing.

Until now, that I read about a new CSS trick:

.container {
   overflow:hidden;
   width:100%;
}

As simple as this! And it works great. Even in Netscape Navigator 4! Boy, that's too much of a lucky one, isn't it? I wonder if it happens to work with the IE family. It seems it works too. That's EXACTLY the kind of solution I was looking for!

No need for additional mark-up at all. Ever!