hasLayoutプロパティがtrueで発生するバグ
hasLayoutプロパティは値がfalseのときに発生するバグがほとんどですが、今回は逆にtrueのときに起こる問題を調べてみました。
hasLayoutプロパティとは
hasLayoutプロパティとはIEが独自に実装している読み取り専用のプロパティです。値はtrueかfalseで、falseの場合に様々なバグが発生します。ほとんどの要素でデフォルト値はfalseなのですが、CSSで下記のような値を指定することによりtrueにすることができます。
プロパティ | 値 |
---|---|
display | inline-block |
height | any value |
float | left or right |
position | absolute |
width | any value |
writing-mode | tb-rl |
zoom | any value |
hasLayoutがfalseのときに起こるバグは多数ありますがここでは触れません。hasLayoutプロパティをtrueにするにはwidthやheightを指定する方法の他に、IE独自実装の「zoom」を使うことも多いです。下記のように「zoom:1」と指定すれば、他のレイアウトに害が少ないからです。
div#foo {
zoom: 1;
}
ただし、この「zoom」はW3CのCSSバリデータでエラーになるのでそれが嫌な人は使わないほうがいいかもです。
hasLayoutプロパティがtrueのときの問題点
では本題です。hasLayoutプロパティがtrueのときに、以下のようなバグが発生します。
- IEでリストマーカーが壊れる
- IE7のズーム機能で拡大、縮小した際に文字が重なる
IEでリストマーカーが壊れる
これはul,ol,liのhasLayoutがtrueだとリストマーカーが壊れます。目も当てられないくらい壊れます。とりあえずIE6とIE7で同じ現象になるのを確認しました。
以下は元のリストです。ul,ol,liは全てhasLayoutはfalseです。普通に表示されてますね。問題ありません。
ul,olのhasLayoutがtrueの場合です。リストマーカーが全部消えちゃいました。
liのhasLayoutがtrueの場合です。ulのリストマーカーが下にずれて、olのリストマーカーが全部1になっているのがわかります。わけわかりません。
このバグの対処法としてはhasLayoutをtrueにしないか、リストマーカーを使用しないことです。widthを指定したい場合などはliの背景画像でリストマーカーを指定するといいと思います。背景画像をリストマーカーの代わりに指定するのは問題ないことも確認しました。
これを考えるとユニバーサルセレクタによる「*{zoom:1}」の指定は避けたほうがよさそうです。
IE7のズーム機能で拡大、縮小した際に文字が重なる
このバグはhasLayoutプロパティがtrueのインライン要素の後にhasLayoutプロパティがfalseのインライン要素が続いた場合に、IE7のズーム機能で拡大、縮小すると文字が重なってしまうというものです。ちょっと言葉ではわかりにくいかもしれないので下記例をご覧下さい。
これは下記ソースをIE7のズーム機能で拡大したときの現象です。
<p>あいうえお<img src="test.gif" alt="test" />かきくけこ</p>
今回img要素には何もスタイルを指定していません。じゃあhasLayoutプロパティ関係ねぇじゃないの?って僕は最初思いました。
しかしなんとimg要素、input要素などはデフォルトでhasLayoutの値がtrueらしいのです。この事実がわかったときはガクブルでした。つまりhasLayoutをtrueにしなければいいという問題ではないのです。
ちなみにem要素などでやってみた場合文字は重ならず、em要素のhasLayoutプロパティをtrueにすると文字重なり現象が起きました。まぎれもなくhasLayoutプロパティが原因のバグということがわかります。しかしem要素はhasLayoutをtrueにしなければいいだけの話です。
対策としては、余計なインライン要素のhasLayoutプロパティをtrueにしないというのがまず大事です。そしてimg要素やinput要素については色々と考えたのですが、後続するインライン要素のhasLayoutプロパティもtrueにするということしか対策が見つかりませんでした。
<p>あいうえお<img src="test.gif" alt="test" /><span style="zoom:1">かきくけこ</span></p>
どうしてもこの方法しか思いつかなかったし、調べても同じような方法しか見つからなかったんですよね。しかしバグ対処で(X)HTMLをいじらないといけないのはどうしても納得いかないというか・・・。思い切ってこんなバグ無視!という選択もあるのだろうか?もし他にナイスな方法で回避する方法をご存知の方は教えてください。
ちなみに、spanに指定するプロパティは別に「zoom」じゃなくてもいいですが、非置換インライン要素にwidthやheightを指定しても無視されるという仕様のためか、span等にwidthやheightを指定してもhasLayoutプロパティはtrueにならないようです。なので現実的に使えるのはやはり「zoom」くらいかなと。
まとめ
今までhasLayoutプロパティはtrueにしとけば問題ないと思ってたんですが、そうでもないということがよくわかりました。それにしてもIE7はクロスブラウザ対応の状況を悪化させてるような気が・・・
- Prev Entry:XHTMLのDTDの読み方のまとめ
- Next Entry:IE7用のハック(*+html body)で指定したスタイルがOperaにも適用される