水無月ばけらのえび日記

bakera.jp > 水無月ばけらのえび日記 > 2003年のえび日記 > 2003年3月 > 2003年3月26日(水曜日)

2003年3月26日(水曜日)

width: auto のフロート

CSS で画像以外のものをフロートしようとしたときに良くはまるのが、フロートには width の明示が必要という罠です。

10.3.5 Floating, non-replaced elements

If 'left', 'right', 'width', 'margin-left', or 'margin-right' are specified as 'auto', their computed value is '0'.

以上、CSS2 10.3.5 Floating, non-replaced elements より

というわけで、非置換要素をフロートするときには width を明示的に指定してやらないと、width の算出値は 0 になります。幅 0 のものがフロートすることになりますが、なにしろ幅 0 ですからうまくありません。まず読めませんし。

ところが、これが IE で表示させると何故か幅 0 になりません。幅を適当に算出してくれて、ちゃんと読めるようにレンダリングしてくれたりします。実は昔、私も某所でこの罠にはまったのですが、当時は Mozilla などインストールしていなかったので、えむけいさんに指摘されるまで気がつかなかったという逸話があります。

そのとき思ったのは、「なるほど仕様的には非置換要素のフロートには width の明示が必要ですけれども、むしろ IE の挙動の方が嬉しいんじゃないのかしら」ということでした。width: auto だと幅 0 というのは、どう考えてもスタイルを指定した者の意図に反する結果にしかならないと思うわけなのです。

……とまあそんな事を思っていたのですが、実はそう思ったのは私だけではなかったようで、最近の CSS2.1 のドラフトを見ると、その部分はこんな記述になっています。

If 'left', 'right', 'margin-left', or 'margin-right' are specified as 'auto', their computed value is '0'.

If 'width' is specified as 'auto', the computed value is the "shrink-to-fit" width.

以上、CSS 2.1 Specification W3C Working Draft 28 January 2003 / 10.3.5 Floating, non-replaced elements より

つまり width は 0 ではなくて、"shrink-to-fit"、すなわち「ぴったりフィットするサイズに縮んだ」幅になります。"shrink-to-fit" という幅については、その後に続けて書かれています。

Calculation of the shrink-to-fit width is similar to computing 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, compute the available width: in this case, this is the width of the containing block minus 'left', 'right', 'margin-left' and 'margin-right'. (Omit 'left' and 'right' if they do not apply to this element.)

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

以上、CSS 2.1 Specification W3C Working Draft 28 January 2003 / 10.3.5 Floating, non-replaced elements より

Roughly と言っていますが本当に Roughly で、特に気になるのは、既にフロートがある場合について考慮していないということです。これ、何も考えずにそのまま実装すると、既存のフロートの横にフロートするとき、既存のフロートを無視して幅を決めることになってしまいます。

まあ常識的に考えれば、フロートは決して重ならないという掟なのですから、既存のフロートが存在しているときは、当然その分の幅は新たなフロートのためには利用できません。ですからその分も "available width" から差し引くべきでしょう。※ちなみに IE の挙動だとちゃんと引かれているようです。

今までの私の経験からすると、フロートの幅を auto にしたい時というのは、複数のフロートを横に並べて擬似的な段組にしたい時だったりするので、肝心のそのときの説明が無いというのは何ともなぁ、と思いました。まあ、これはまだワーキングドラフトなわけで、この辺りの説明が変わる可能性は高いですし、この仕様自体がどうなるか分からないわけですが……。

関連する話題: メモ / CSS / CSS2 / CSS2.1

border の有無でマージン相殺が変わる

偶然にも CSS の話題が続きますが……。

マージンの相殺という、なかなかマニアックな点に触れているところに期待が持てる連載なのだが、ひとつ気になる点があった。ボーダーの有無でマージンの相殺の挙動が変わるようなことが書かれていることだ。私の記憶によると複雑なルールではなかったはず。

以上、りゅうさんの偽偽夜食日記 2003年03月24日 より

元記事を読んでいないので想像ですが、これはおそらく、あるボックスの中に別のボックスが入れ子になっていて、両方にマージンが設定されている場合の話でしょう。この場合、外側のボックスに border も padding もないと、マージンは重なります。しかし border や padding があると重なりません。

CSS2 の "8.3.1 Collapsing margins" には、冒頭に以下のような記述があります。

In this specification, the expression collapsing margins means that adjoining margins (no padding or border areas separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.

以上、CSS2 8.3.1 Collapsing margins より

(no padding or border areas separate them)という注意書きが味噌で、2つのマージンの間に padding も border もなければマージンは重なり得るし、そうでなければ重ならないわけです。

※もっとも、仕様のこの記述にはちょっと微妙なところがあります。padding or border areas という言葉の解釈の仕方によっては、「border: none; padding: 0; であっても、そこには幅 0 の border 領域や padding 領域が存在しているので、マージンは重ならない」と解釈することも出来そうです。しかしそう解釈してしまうと、ネストされた要素のマージンは決して重ならない事になってしまいます。(which may be next to one another or nested) と書かれているからにはネストされていても重なり得るということですから、そのような解釈は間違いと言えるでしょう。

具体的な例を出しますと、たとえば以下のようなマーク付けに対して……

<div id="div3">
<div id="div2">
<div id="div1">
<p>foo</p>
</div>
</div>
</div>

以下のようなスタイルを適用します。

#div1{
margin: 1em;
}
#div2{
margin: 2em;
}
#div3{
border: red solid 1px;
bckground: #fff; color: #000;
}

すると、中のブロックのマージンによって、あたかも div3 に padding: 2em 3em; が指定されているかのような見た目になります。上下のマージンは重なるので、div1 の 1em と div2 の 2em が重なって合計で 2em となります。※ちなみに左右のマージンはこの場合でも重ならないので、1em と 2em は重ならずに 3em になります。

このスタイルを以下のように変えると……。

#div1{
margin: 1em;
}
#div2{
margin: 2em;
border: #fff solid 1px;
}
#div3{
border: red solid 1px;
bckground: #fff; color: #000;
}

1px の border が指定されただけなのですが、もはや上下のマージンは重なりませんので、div1 の 1em と div2 の 2em は合わさって 3em となります。まるで div3 の上下 padding が 1em 増えたかのように見えます。※ちなみに左右の距離は 1px しか変わりません。

関連する話題: メモ / CSS / CSS2 / CSS2.1 / もののけ / りゅうさん

鳩丸トップの謎カウンタがリセット

久々に鳩丸のトップを見たら、謎のカウンタのようなものの数字が 8144 に。

これ、いつもあんまりよく見ていないのですが、たしか 30万は超えていたはず。いつのまにかリセットされていたようです。

せっかくなのでこの機会に告白しておくと、この謎のカウンタのようなものは、そもそも「FPROG 会員ホームページ存在確認カウンタ」を設置しようとしたときに、フィンローダさんの ID である "SDI00344" を誤って "SDIO0344" としてしまったのが発祥です。そうしたら何故か独自のカウンタっぽく動作してしまい、それでそのまま放置してあるというとんでもない代物。

その typo された ID は存在しないものなので、誰もこのカウンタの管理を行うことが出来ないのでした。つまり、理論的にはリセット不能なはずなのでして、どうしてこの数字が減ったのかは全くの謎です。単純にデータファイルが吹っ飛んだのかもしれません。

関連する話題: 出来事

最近の日記

関わった本など