よくある「float で組む」失敗

郵政民営化の話が面白かったので今更ながら bewaad.com を RSS リーダに登録。

で、内容とは全然関係ないけど、CSS のレイアウトがおかしいのに気付いたので一言*1。サイドバーと本文のブロック要素を float でレイアウトしてますが、ウィンドウの幅が狭い時に本文側のブロックが遥か下方に飛んでいってしまいます。

この現象、サイドバーのあるサイトでたまに見かけるんですが、通りすがりで見かける時は「ふざけんな」とか思ってもう見ないだけですが、bewaad さんとこはそうもいかないので。。。ちょっと真面目に考えてみます。

これは float レイアウトの衝突回避(float 要素同士が重なり合わないようにするルール)が働いて後ろに出てきた方の float 要素が下に配置されるせいです。重ならせないことを意図して、それぞれのブロックの width プロパティを % 指定にして合計 100% にならないようにしていますが、CSS の width プロパティは内容領域の幅なので(参照: CSS2 10.2,8.1)、ブロック全体の幅はこれに左右のパディングとボーダーとマージンの幅を足した値になります。そして、float の衝突判定はマージンまで含めた全体の矩形に対して行われます(CSS2 9.5)。

bewaad.css の場合*2、左右のボーダーが px、パディングが em で指定されているので、ウィンドウの幅および文字サイズによってはサイドバーと本文のブロックの幅の総和が 100% を越えてしまい、衝突回避が発動してしまいます。

ボーダー、パディング、マージンの幅も % 指定して、トータル100%以内に指定できれば衝突を未然に回避できるのですが、困ったことにボーダー幅は % 指定ができません(CSS2 8.5.1)。ボーダー付けるのは諦めるか、超狭いウィンドウをサポートしないか(文書構造を変えたくないなら)。。。

でも、firefox ではなぜか padding を % 指定すると overflow:auto の時に問答無用で横スクロールバーが出てしまうというバグ? もあるようですね。。。

で、ここで本音を。float でレイアウトを組むな と言いたい。某ワープロCSS の float レイアウトを実装した立場からのお願いです。

元々 float はきっちりしたレイアウトをするためのものではなく、専ら本文中に出てくる図や表のレイアウトを機械に任せて無難に自動配置するためのものです。複数の float が隣接した時の配置ルール(衝突回避しながら配置するルール)を利用して「レイアウトを組む」のは正直言って abuse だと思います。

abuse かどうかは別にしても、実用上も疑問があります。float は配置ルールがかなり厳密に仕様化されているとはいえ、本来が「よきにはからえ」的なものですので、技術者の立場からすると他に大事な事(実行効率とか後方互換性とか)がある場合は「要するに float 同士が衝突しなきゃ OK でしょ?」と手を抜く、あるいはデバッグの優先度が下がるというのはありえます。ていうか実際あります。ありますとも! IEfirefox で float レイアウトの振る舞いが微妙に違うのもたぶんそのせいだと思います(IE5 の頃はもっと酷かった)。

float で組むのやめろというなら対案は? と言われると、まず本文のブロックで float は使わない。そして本文に % 指定でサイドバーの分マージンをあけておいてそこにサイドバーを float か position: absolute を使って配置すればよいかと。でも firefox は overflow プロパティでスクロール可能になるとマージンが float を避けてしまうバグがあるようですね。。。position: absolute もブラウザによって微妙に振る舞いが違ったりして困るんですが。どちらにしろフッタをサイドバーの下に積むのは無理かも。

ていうか CSS であんまり無理なレイアウトはしないほうがいいと思います。正直言って機械生成の HTML なら table でレイアウト組むのもありでしょう。table 使うと携帯や PDA で見るとき困る云々ってのも、こんだけサイドバーやらナビゲーションバーやらがごちゃごちゃあったらどっちにしろ見れたもんじゃないし。

[id:rna:20050704#p4] にちょろっと書いた style abuse というのはこういう話だったのでした。

追記: 念のため…

float が全部ダメってわけではなくて、本文の流れとは別の図・表・コラムなどを float で配置するのは全然構わないです。ただし、基本的には「おまかせ機能」なのでレイアウトを精密に制御するのは諦めたほうがよいと思います。特に図表が沢山かたまって出てくる場合は、複数の float を積むのは避けて table を一つ float にしてその中に図表を並べる方が無難かと。。。

あと、今更こんなこと言うのもなんですが、僕は仕事として Web デザインをやったことはほとんどないので(10年ほど前にバイトでやったっきり)、上の議論がプロの現場で通用する話なのかどうかよくわかりません。Web デザイン業界でこのへんどういう議論があるのか、トラバなどで教えて頂けるとありがたいです。

また僕が float の実装をやっていたのは5年ほど前の話で、最近のブラウザの実装については厳密に調査してるわけではないのでブラウザ間の互換性については勘違いなどあるかもしれません。


*1:ていうか昔書きかけてお蔵入りにした記事を再利用。

*2:ここは firefox のバグ(overflow プロパティで出てきたスクロールバーがホイールでスクロールできない。)回避用だかなにかで alternative な CSS を選べるようになってるんですが、こちらも同様です。