IE7のズーム機能を使うと、ラジオボタンやチェックボックス、文中に入れた画像がおかしくなります。こんな風に。
<input type="radio" />ウェブ全体から検索
<input type="checkbox" />日本語のページを検索
<img src="/clip/cmn/img/entry-bg-01.gif" />オマケ
これを直す方法。
IE6までは、問題のある要素にheight:0を指定するという、holly hackと呼ばれるバグ対処方法で、数々の問題のあるバグが解決されてきました。IE7になっても、コレに変わり、min-height:0を指定すれば直るじゃん!と思ってました。
しかし、その方法でもこれは直らない・・・。他のズーム機能のあるブラウザではこんなこと起こらないのに、どうすればいいか到底見当もつかない・・・ひどすぎるIE7・・・。と思っていたんだけれど、これは直せるということを今日知った。
具体的には、以下の指定をCSSで行い、この、めり込むインライン要素の横にある要素もちゃんとマークアップしてあげる。
*{
zoom:1;
}
<input type="radio" /><span>ウェブ全体から検索</span>
<input type="checkbox" /><span>日本語のページを検索</span>
<img src="/clip/cmn/img/entry-bg-01.gif" /><span>オマケ</span>
zoomというのは、IEの独自拡張プロパティで、拡大率を示します。これがIE6のholly hack的な役割をするようです。コレで直ります。めでたし。
holly hackで何故色々直るのかということにも関係してる話です。
IEでは、(X)HTML内の全ての要素にhasLayoutプロパティというものが存在しています。これは何かというと、その要素が、レイアウト情報を持つのかということです。例えば、divを配置しただけだと、こいつは、親のボックスの高さによって、自動的に伸びたり縮んだりします。この時点では、こいつはhasLayout=falseの情報をもってる。レイアウト情報はありません。
しかし、width:300pxを指定したら、このdivは、hasLayout=trueになります。hasLayout=trueになることで、親が伸びたり縮んだりしても、こいつ自身は常に300pxになります。floatさせたり、height,widthを指定したり、positoin:absoluteを指定したりしてあげることで、どんな要素もhasLayout=trueとして扱われるようになります。
IEは、hasLayoutを持っている要素についてのみ固定化すればよいため、全てのhasLayout=falseな要素は、特に計算すること無しに上から詰めていけば問題ないでしょっていう仕組みらしいですな。
ところが、IEは馬鹿なので、floatさせたりposition:relativeさせたり、backgroundを指定したりした場合、配置の計算がいまいちちゃんとできないみたいなんです。それで、背景がちかちかするだの、floatがクリアされんだの、幅がでかくなってしまうだのという現象が発生してしまうのです。そこで、そいつらにちゃんとhasLayoutを与えてやろうということで、height:0を指定してあげたのが、holly hackの正体なのでした。hasLayoutを与えてやることで、そいつらにちゃんとレイアウト情報を持たせてあげることができ、ちゃんと表示されましたということになるみたいです。たぶん。
| display | inline-block |
|---|---|
| height | any value |
| float | left or right |
| position | absolute |
| width | any value |
| writing-mode | tb-rl |
| zoom | any value |
さて、IE7の拡大で何故バグるのかというと、このラジオボタンやチェックボックス、画像といったインライン要素は、hasLayout=falseだからなんです。ズームした時に、そいつらはhasLayout=falseなので、幅も高さも無かったことにされてしまい、ぐしゃっとなってしまうという、よく分からない動作をしてしまいます。これは、IE7のバグです。hasLayout bugとでも言ったもんでしょうか。
MSDNによれば、右記のプロパティのどれかを指定すればhasLayout=trueになるとのこと。
この中で、一番問題ないのが、zoomです。zoom:1にしておけば、拡大率1なので、そのまま表示されるだけなので。初めに、min-height:0をやればIE7で直るとか書きましたが、それは、ブロック要素のみの話だったのです。インライン要素に指定されたwidthやheightは無視されるため(これはW3CのCSS2の仕様に則した動作です)、インライン要素にmin-height:0を指定したところで、無視されます。だから、zoom:1を使います。
そして、隣り合う文字もspanなり何なりでマークアップしないといけないです。
<input type="radio" />ウェブ全体から検索
のままだと、「ウェブ全体から検索」はそもそもhasLayoutがあるどころか、(X)HTMLの要素にもなっていないため、hasLayout bugにやられてしまいます。
なので、
<input type="radio" /><span>ウェブ全体から検索</span>
とやることで、このラジオボタンもspanもhasLayoutを持つため、直りましたということです。*{zoom:1}は、かなり万能のIE7対応CSS Hackってことですな。まぁこのおかげで微妙に描画が他のブラウザと変わってくる部分も無いことは無いのですが、とりあえず、やたー
しかしまぁ、zoomってのは、IEが、ズーム機能のために追加した独自のプロパティです。CSS2にも当然無いため、W3Cのバリデータでバリデートすると当然エラーになります。せっかくズーム機能追加したのに、こんなバグ起こって*{zoom:1;}なんてやられちゃうんじゃ、そもそもhasLayout自体全然意味無いよなぁ…。
ついでに、MSDNのhasLayoutの解説ページでは、こんなことすることでhasLayout機能が活用できるぜ!ってhackが載ってたりします。中身見るとあーそんな便利なことがあるのかということとかもあったりするんですが、なんかW3CとかどうでもいいんでしょうかIEは・・・。Operaをみならってほしいもんです。
以下、参考ページ
以下、当サイトの関連記事
このエントリーには続きがあります。
A.T 2007/5/12 (01:53)
hasLayout 知らなかった
よく言うIEでheightを明示させるって言い方は、
hasLayoutをtrueにするってのが正しいと。
なんでこんな重要なプロパティ勝手に追加してんだIEは・・・
Takazudo 2007/6/22 (12:08)
でもたまにhasLayout効果で実現できる便利効果もあったりもする。
floatとあわせて使うと、display:table使わんとできない効果もできたりするし。
てかIEがmozillaエンジンになればいいのに!