KOJIKA17

float解除の決定版。clearfixを考えたら、進化した。

現在floatを解除する方法として、"clearfix"がよく使用されていると思います。
しかしclearfixが初めて公開されたのが、2004年5月8日。
それ以来、7年間ほとんど形を変えずにclearfixが使用されてきました。
ブラウザもCSS3を多く対応してきている中で、「それで良いのか?」という疑問を新しい形を模索してみました。

[2013-06-20]追記

このページの情報は古くなっている可能性があります。

floatを解除する手法のclearfix と 次世代のレイアウトの話をあわせて、お読み頂くことをおすすめします。

clearfixをおさらい

オーストラリア人のTony Aslettという方が、cleafixを考えました。
考え出されたCSSは以下の通りです。

.floatcontainer:after{
  content: "."; 
  display: block; 
  height: 0; 
  font-size:0;	
  clear: both; 
  visibility:hidden;
}
	
.floatcontainer {display: inline-block;} 

/* Hides from IE Mac */
* html .floatcontainer {height: 1%;}
.floatcontainer {display:block;}
/* End Hack */ 

現在使用されているclearfixと、ほとんど変わっていません。

clearfixの解説
clearfixでfloatを解除 | d-spica

clearfixのポイントと改善点

clearfixのポイントは2点です。

  • ::after
  • hasLayout

::afterを考える

Tony Aslettの作ったclearfixで長くなっている部分です。

.floatcontainer:after {
  content: "."; 
  display: block; 
  height: 0; 
  font-size:0;	
  clear: both; 
  visibility:hidden;
}

ソースが長くなっている原因として、content: ".";が問題になっています。
contentが"."でなければ、実はかなりすっきりします。

なぜcontent: ".";なのか、調べた記事がありました。
clearfixはちゃんと考えられていた -3.5ping.org-

コメントの方まで読み進めると、Netscapeが原因だったようです。
今はNNなんて対応している人もいないでしょうし、::afterを完結にすることができます。
短くした::afterは以下の通りです。

.clearfix:after {
  content: ""; 
  display: block; 
  clear: both;
}

hasLayoutを考える

IE6, 7は::afterに対応していませんが、hasLayoutという読み取り専用のプロパティを持っています。
これによって子要素でfloatを使用しても、親要素の高さを出すことができます。
hasLayoutの値を切り替えるプロパティは下記の通りです。

プロパティ
displayinline-block
heightなんか値入れて
floatleft か right
positionabsolute
widthなんか値入れて
-ms-writing-modetb-rl
zoomなんか値入れて

現在この中でclearfixでよく使用されているプロパティは

  • display:inline-block;
  • height:1%(min-height:1%)
  • zoom:1;

でも良く考えたら、全て微妙です。
zoom:1はIEの独自仕様ですし、heightを使用する場合は、IE6,7に対応させるために2つのプロパティが必要です。
display:inline-blockもボックスの要素を変形させることになります。

hasLayoutのスイッチを見た時に、一番理に適ったプロパティはwidthかなと思いました。
子要素を囲む要素として、divやulなどデフォルトCSSがdisplay:blockのプロパティのものが多く、display:blockのプロパティの場合、width:100%で問題ないと思ったからです。

現在のブラウザ状況に適したclearfix

上記を踏まえ見直したclearfixが以下の通りです。

.clearfix {width:100%;}
.clearfix:after {
  content: ""; 
  display: block; 
  clear: both;
 }

width:100%;としているので別のwidthと干渉しないかという疑問もあると思いますが、CSSの優先順位でclearfixの記述よりも下にwidthのプロパティを指定しているのあれば、全く影響ありません。

現在のブラウザ状況に適したclearfixデモ

擬似クラスを意識したclearfix

クラスでclearfixを使い続けることは全く問題ありませんが、CSS3の:first-child, nth-child(n),:rootなどの 擬似セレクタなどが登場し、HTMLにクラスを記述しなくてもコーディングができる流れに変わってきています。
そこでHTMLにクラスを当てないで、floatを解除する方法を考えてみました。
ソースは以下の通りです。

*:after {
  display:block;
  clear:both;
} /* この記述は固定です */

element {width:100%;} /* clearfix IE6, 7 */
element:after {content:"";} /* clearfix */

#content {width:600px;} /* clearfix IE6, 7 */
#content:after {content:"";} /* clearfix */

最新のモダンブラウザやIE6, IE8(実機)で検証した結果、上記ののようなソースになりました。
解説すると長くなるので、割愛します。

使い方は、*:after部分を始めに記載し、floatの親要素であるidやclassにwidthに値を入れてやります。
widthに値が入っている場合は、何もしなくて大丈夫です。
そしてfloatの親要素:after {content:"";}の記述を行えば、floatを解除を行うことができます。
名前をつけるとしたら、elementfixとか?

HTMLにクラスを使用しないclearfixデモ

実験的に考えてみましたが、IE7, IE9は実機テストを行っていないので、ご報告があると嬉しいです。
IE9などが問題なければ、実用も可能だと思います。

[2011-4-6]追記

width:100%;について

@shimaelさんにwidth:100%について言及して頂きました。 width:100%;だと、clearfixをかける要素にpadding、marginがあると、親要素よりもはみ出てしまう場合がありました。
IE6は収まっていますが、単にバグなので状況は変わっていません。

clearfixにpadding, marginをかけたデモ

width:100%は、一人でコーディングする場合は問題ないのですが、複数人で制作を行う場合は他の人が触りにくい状況になる可能性があります。
hasLayoutを行う場合、結局zoom:1;に落ち着くかもしれません。

/* 20110406クラスあり修正版 */
.clearfix {zoom:1;}
.clearfix:after {
  content: ""; 
  display: block; 
  clear: both;
}
/* 20110406クラスなし修正版 */
*:after {
  display:block;
  clear:both;
} /* この記述は固定です */

element {zoom:1;} /* clearfix IE6, 7 */
element:after {content:"";} /* clearfix */

overflow:hidden;について

twitterなどのソーシャルメディアのコメントの中に、「overflow:hidden;を使ってるよ」というコメントをいくつかありました。
clearfixを使用しなくても、overflow:hiddenでも親要素の高さを算出することが可能です。
調べてみると、overflow:visibleなどとoverflow:hiddenでは、高さの計算方法が違うらしく、floatや一部のabsoluteに対しても親の要素に含めて計算してくれるようです。
ただしoverflow:hidden;はclearしている訳ではないらしい。