IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

めも

このメモについて

  • id:amachang の私的な学習目的
  • IE6 の標準モードに関するバグ

いろいろとポイント

  • layout
    • IE6 の視覚整形モデルの中で要素は、大きく分けて layout を持つ要素と、 layout を持たない要素に分けることができる。
    • layout を持つ要素とは、自分のサイズや位置に責任を持つ要素である。
    • layout を持つ要素は、四角形の領域を作る。
    • layout を持たない要素は、直近の layout を持つ要素のサイズおよび位置と、そこの間にあるすべての要素の margin, padding, border によってその開始点、折り返し点が決まる。
    • layout を持たない要素は、四角形の領域を作らない。上下左右の間隔を保持しているだけに過ぎない。
    • layout を持たない要素間の上下マージン(相殺されるマージン)は二つの要素間の共有のもので、ある要素特有の管理下にはない。(つまり、要素のレンダリングのバグを直したいときにマージンは影響しないことが多い)
    • 要素に layout を与える場合は style に zoom: 1 を指定すればいい

(border-left または border-right) と padding-bottom の問題

以下の HTML によって発生する

http://amachang.art-code.org/ierendering/000.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<title>IE Rendering Test</title>
</head>
<body>

    <!-- border-left と padding-bottom を持つ layout を持たないブロックレベル要素 -->
    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- この要素の最後に layout を持たないブロックレベル要素 -->
        <div>layout を持たないブロックレベル要素</div>

    </div>

    <!-- この要素が 2em (ボーダーの幅 x 2)だけずらされる -->
    <div>ずれてますか?</div>

</body>
</html>
ずれないパターン 1

http://amachang.art-code.org/ierendering/001.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- この最後の要素をインライン要素にする -->
        <span>layout を持たないブロックレベル要素</span>

    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 2

http://amachang.art-code.org/ierendering/002.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- この最後のノードをテキストノードにする -->
        テキストノード

    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれる幅が違うパターン 1

http://amachang.art-code.org/ierendering/003.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- border-bottom を付ける -->
        <div style="border-bottom: 1px solid blue;">layout を持たないブロックレベル要素</div>
    </div>

    <!-- 2em ではなくて 1em しかずれない -->
    <div>ずれてますか?</div>

</body>
ずれる幅が違うパターン 2

http://amachang.art-code.org/ierendering/004.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- padding-bottom を付ける -->
        <div style="padding-bottom: 1px;">layout を持たないブロックレベル要素</div>
    </div>

    <!-- 2em ではなくて 1em しかずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 3

http://amachang.art-code.org/ierendering/005.html

<body>

    <!-- border-bottom を追加 -->
    <div style="border-left: 1em solid blue; border-bottom: 1px solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <div>layout を持たないブロックレベル要素</div>
    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 4

http://amachang.art-code.org/ierendering/006.html

<body>

    <!-- layout を与える -->
    <div style="zoom: 1; border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <div>layout を持たないブロックレベル要素</div>
    </div>

    <!-- ずれない -->
    <div>ずれてますか?</div>

</body>
ずれないパターン 5

http://amachang.art-code.org/ierendering/007.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">

        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>
        <div>ほげほげほげほ</div>

        <!-- layout を与える -->
        <div style="zoom: 1">layout を持つブロックレベル要素</div>
    </div>

    <!-- ずれない --> 
    <div>ずれてますか?</div>

</body>
ずれる幅が違うパターン 3

http://amachang.art-code.org/ierendering/008.html

<body>

    <div style="border-left: 1em solid blue; padding-bottom: 1px;">
        <!-- からっぽ -->
    </div>

    <!-- 1em ずれる -->
    <div>ずれてますか?</div>

</body>
現象
  • 要素の下辺( margin を考えない)が padding で、最後の子要素が non-layout ブロックレベル要素のときに発生する
  • 最後の子要素がインライン要素の場合に発生しない
  • 最後の子要素に対して borderpadding を指定した場合にずれる幅が変わる(半分になる)

はみ出した箇所が表示されない問題

http://cssbug.at.infoseek.co.jp/detail/winie/b025.html
http://cssbug.at.infoseek.co.jp/detail/winie/b041.html
http://cssbug.at.infoseek.co.jp/detail/winie/b046.html

実際の例と回避

http://amachang.art-code.org/ierendering/009.html

<body>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="zoom:1; border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
        <div style="zoom: 1; position: relative; margin: 0 -1em; border: 1px solid red">端っこ見えてます?</div>
        あああ
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

    <div style="border: 1px solid blue; margin: 2em;">
        あああ
        <div style="zoom: 1; position: relative; margin: -2em 0 0; border: 1px solid red">端っこ見えてます?</div>
    </div>

</body>

floatclearbackground の問題

layout を持たない親要素の中で floatclear すると背景が margin 領域まで広がる。そして、自分の兄要素の layout を持たないものが消える(消えると言っても実際に消えるわけではなく、「再描画」が伝搬しなくなる。スクロールによって出現する)
この消え方を Peek-a-boo というらしい
http://amachang.art-code.org/ierendering/010.html

<body>

    <div style="margin: 1em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
    </div>

    <div style="margin: 1em; zoom: 1; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right">かかか</div>
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
    </div>

    <div style="margin: 2em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right"></div>
    </div>

    <div style="zoom:1; margin: 2em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right"></div>
    </div>

    <div style="margin: 2em; background: gray;">
        <div>あああ</div>
        <div style="position: relative">いいい</div>
        <div style="zoom: 1">ううう</div>
        <div style="zoom: 1; position: relative">えええ</div>
        <div style="float: right">おおお</div>
        <div style="clear: right"></div>
    </div>

</body>
基本的には以下の有名なバグも仕組みは同じ

http://www.positioniseverything.net/explorer/peekaboo.html
http://amachang.art-code.org/ierendering/011.html

<body>
    <div style="background: gray">
        <div style="height: 20em; float: left">
            <br />
            <span>&nbsp;Float&nbsp;
                <br /><br />
                <a href="#">&nbsp;test link&nbsp;</a>
            </span>
        </div>
        This is bare text. <a href="#">Test link</a> 
        <div style="border: 3px solid #f00; background: #dde;">This is text inside a div. <a href="#">Test link</a></div>
        This is bare text. <a href="#">Test link</a>
        <div style="border: 3px solid #0c0; background: #dde;">This is text inside a div. <a href="#">Test link</a></div>
        This is bare text. <a href="#">Test link</a>
        <div style="border: 3px solid #00f; background: #dde;">This is text inside a div.  <a href="#">Test link</a></div>
        This is bare text. <a href="#">Test link</a>
        <div style="clear: left">Clearing div</div>
        <div style="border: 3px solid #00f; background: #dde;">This div is after the cleared div. (purple box) If cleared div 
        does not touch float, bug is not triggered. <a href="#">Test link</a></div>
    </div>
</body>
float よりも clear が原因

float というよりもボックス内で clearance マージンが設定されたかどうかで発生するかが決まる。
たとえば、コンテンツを文字で満たして float 要素を囲み、 clearance マージンの設定が必要のない状態にするとこの問題は発生しない。( clear を指定した要素の margin-top を clearance よりも大きくしてもこの問題は発生しない)
あと、 clearance マージンより下方向にコンテンツがない場合は、 Peek-a-boo は起きない。
重要なことは、 clearance マージンと non-layout なブロックの背景。

float の 3px

このバグは。。。 3px くらい空いてほうがいいでしょ的な気分で付けたとしか思えない。。。
(margin-left or margin-right): -3px くらいしか解決策はないのかな?

(続くかも)