非置換要素の幅を明示せずにフロート

CSS で非置換要素 (img とか objectとかフォームのコントロール系とか以外、ってことね) に float プロパティを指定する場合、同時に幅を具体的な数値で明示しなければならない、とよく言われる。さもなければ幅が 0 として扱われちゃうよと。

でもその仕様は CSS 2 での話で、CSS 2.1 にそのような記述はない。そのかわり、幅を明示せずに非置換要素をフロートした場合、その幅は内容に合わせて縮む (shrink-to-fit) とされている。

If ‘margin-left’, or ‘margin-right’ are computed as ‘auto’, their used value is ‘0’.

If ‘width’ is computed as ‘auto’, the used value is the “shrink-to-fit” width.

Calculation of the shrink-to-fit width is similar to calculating the width of a table cell using the automatic table layout algorithm. Roughly: calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur, and also calculate the preferred minimum width, e.g., by trying all possible line breaks. CSS 2.1 does not define the exact algorithm. Thirdly, find the available width: in this case, this is the width of the containing block minus the used values of ‘margin-left’, ‘border-left-width’, ‘padding-left’, ‘padding-right’, ‘border-right-width’, ‘margin-right’, and the widths of any relevant scroll bars.

Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).

(Visual formatting model details: 10.3.5 Floating, non-replaced elements)

幅を指定しないということはすなわち、width プロパティに初期値である auto が指定されていることになる。通常フローのブロックレベル要素で widthauto の場合、その幅は親要素内でいっぱいまで広がるけど、フロートした要素の場合は shrink-to-fit という方法で幅が算出されることになる、と。この shrink-to-fit というのはテーブルのセルと同じような挙動で、内容に応じて可能な限り小さく縮むというもの。

この柔軟なアルゴリズムはかなり使える。例えば横に並べたナビゲーション項目を画像ではなくテキストで作りたい場合とか。でもこの shrink-to-fit アルゴリズム、あまり多く紹介されていない気がする。僕もフロートするなら幅の指定も必須、とついこないだまで考えていたし。

やはり非置換要素のフロートというとマルチカラム・レイアウトに利用されることが多いから、自然と幅を明示することになるからかな。あと、どうも古いブラウザでバグがあるらしい。

でも少なくとも IE 6 を含むモダン・ブラウザではサポートされていて、幅が 0 と解釈されることはない。

ちなみにこの shrink-to-fit って言い回し、Levi’s の 501 からきてるのだろうか?