以下の文書はウェブ制作者にとって非常に有用な文書でしたが、サイト自体が消滅していたようなのでキャッシュからサルベージしました。 この文書を公開することについては翻訳者さまへメールで連絡をとっていますが、まだご返答を頂いていません。なので、申し出によっては公開を止める可能性もあります。何か問題がありましたら eiji.fukushima@gmail.com までご連絡ください。

また、以下の文書は、ほぼ元のままで手を加えておりません。従ってリンク切れしているものもあります。また、画像はサルベージできませんでした。

公開者
福島英児
公開日
2007-07-31T11:05:00+09:00
この文書について

Mac版 Internet Explorer 5 の CSS バグと回避方法

原文題 CSS Hints for Internet Explorer 5

私たちがよく知っているように、Windows と Macintosh 版の Microsoft Internet Explorer 5 はそれぞれ異なる描画エンジンを持っており、そのため同じ HTMLCSS にも違う挙動をします。これは、ウェブ制作者は両方のブラウザで動作確認をしなければならないことを意味します。ひとつの環境でうまく表示できたからといって、他のブラウザでも同じように表示できると思い込むことはできません。

一般的に、Mac 版の IE は、より厳格にウェブ標準仕様に従っており、対応しています。その一方、Windows 版 IE は Microsoft 独自仕様のスタイルや JScript メソッドに対応しています。そして、Mac 版は CSS 対応に関しては大きく先んじています。例えば、Windows 版が未だに実行できない position:fixed をサポートしています。

Mac 版 IE は、他の多くのブラウザと同じようにバグや特異な性癖を持っており、そうと知らないウェブ制作者をけつまづかせます。この記事は、よく見かける3つのタイプの問題について記述しています。

  1. position:relative 関連のバグ
  2. 要素に余分な margin が出現するバグ
  3. overflow 宣言を実行する際のバグ

これらのバグは、OS 9 と OS X の両方のプラットフォームにおいて Mac版 IE 5 の全部のバージョンで発生します。

コメント内のバックスラッシュでハック

幸いなことに、ウェブ制作者はこれらの不具合に対抗する策があります。役立つ CSS ハックを使えば、ブラウザ振り分けや CSS 分割に頼らなくても特殊なスタイルを定義できるようになります。

使い方: MacIE は、 CSS コメント中のバックスラッシュ \ を正規表現を読むかのように次の文字のエスケープコードだと解釈します。このまちがった挙動の好都合なことは、コメントの終点マーカーをエスケープできることです。以下のようにすれば IE は スタイル指定を正しく解析できなくなります。

要素 {
 スタイル : MacIE用 ;
}

/*
 コメントの終点がエスケープされたコメントです。
 以下のスタイルは IE にはコメントの一部と見なされて
 読み込まれません。
\*/

要素  {
 スタイル : 他のブラウザ用。前記のスタイル指定を上書き。;
}

/*
 今度のコメントは、普通の終点を持つコメントです。 
 IE はこのコメントの終点を前のコメントの終点と見なします。
*/

これで IE のためのスタイル定義をして、他のブラウザのためにはそれを上書きできるようになりました。このハックで多くの CSS 関連の不具合を解決できます。

position:relative 関連のバグ

(訳者註: 以下の文章は CSS が有効な視覚ブラウザで見ることを前提に書かれています)

position プロパティには4種類の値(static, relative, absolute, fixed)のうちひとつを指定します。static はデフォルトの値です。fixed はまだ Windows版 IE は対応していません。ウェブ制作者はよく position:absolute を使い、position:relative を避ける傾向にあります。

要素に相対的な位置指定を与えたとき、その要素は最初はページ普通の位置に置かれますが、新たに topleft プロパティを定義することで移動します。例えば、この段落の topleft を 10px にしたので、ちょっとだけ斜めに移動しています。

この効果は極めて有用です。何が有用かと言えば、相対配置された要素は position:absolute で絶対配置された要素のコンテナになることです。もしこんなスタイルの要素があったとします。

要素 {
 position: absolute;
 top: 10px;
 left: 100px;
}

…これは通常ブラウザウィンドウの左上隅から 100,10 の座標に配置されます。しかし、この要素の祖先要素が position:static 以外の時、要素はその祖先要素から相対的な位置に配置されます。

このように、position:relative で相対配置した要素は、絶対配置した要素のコンテナとして使うことができます。

改行して
改行して
さらに、この段落を相対配置しました。 また、em要素を 100,10 の座標に絶対配置しました(「これは強調」の部分)。座標は、ブラウザウィンドウの左上隅ではなく、この段落の左上隅を基点として用います。だから em はこの段落内にまだあるのです。 これは強調。

position:relative はこのような効果のために用いられるだけでなく、時折見苦しいサイドエフェクトを IE に与えます。以下の通りです。

position:relative のまちがった継承

バグ: 相対配置された要素の内部にある要素は、親要素から position の値と leftright プロパティをまちがった形で継承します(だが top と bottom は継承しません)。

例:

div#container {
 position: relative;
 border: 1px solid #000000;
 top: 50px;
 left: 50px;
 width: 200px;
}

.testdiv {
 position: static;
 border: 1px solid #000000;
 background-color: #ffffff;
 padding: 10px;
 margin: 0px;
}

コンテナの内部の <DIV>position プロパティは明示的に static に指定しました。正しい描画は以下の Mozilla のスクリーンショットです。

コンテナ内部の DIV は両端揃って並びます。

MacIE 5 では、次のような描画になるでしょう。

コンテナ内のボックスが横にずれます。

不可解なことに、IE はすべての DIV 要素(最初のひとつ以外)を 50px 右に移動します。このような DIV 要素は position(relative)と left(50px)プロパティの値を親要素から継承します。

対策方法: 無し。幸いにも、このようなスタイルにする需要はそれほど大きくありません。

テーブルと絶対配置要素

バグ: position を定義していない(従って static となる)テーブル内の絶対指定した要素を配置するとき IE はテーブルが position:relative であるかのような挙動を常にします。絶対配置する要素の座標は、ページの左上隅ではなく、テーブルの左上隅からの相対的な地点になります。テーブルに position:static を明記して定義しても、この問題は回避できません。

例: 以下のスクリーンショットのように、クラス container を持つ要素はテーブルで、クラス testdiv の要素はそのテーブルセルのひとつの中にあります。

<table class="container" border=2>
 <tr>
  <td>
   Blah!
   <div class="testdiv">
    This is the test DIV in the table
   </div>
  </td>
  <td>
   Blah!
  </td>
 </tr>
</table>
.container {
 position: static;
 margin-top: 50px;
 border: 1px solid #000000;
}

.testdiv {
 position: absolute;
 top: 50px;
 left: 50px;
 border: 1px solid #000000;
 padding: 10px;
}

testdiv は、コンテナが position:static なのでブラウザウィンドウから相対的に配置されなければなりません。

Opera 6 は正しく描画します。testdiv は完全にブラウザウィンドウから相対的に配置され、テーブルの位置に影響されません。

しかし、IE はあたかもテーブルに position:relative 指定がされてるかのように、テーブルから相対的な位置に testdiv を配置します。また、<DIV> はだいたいテーブルの内側にフィットするくらいに小さく縮みます。

(面白いことに、Mozilla には正反対のバグがあります。Mozilla は、テーブルが position:relative である時も、テーブル内部の絶対配置要素をテーブルから相対的に配置することができません。 )

対策方法: 無し。テーブル内部の要素を絶対配置しないようにしましょう。

margin

隠れた margin

バグ: 絶対配置要素をブラウザウィンドウの右もしくは底のへりに配置すると、謎の margin が発生し、不必要なスクロールバーが出現する原因となります。

例:

div.container {
 height: 150px;
 width: 200px;
 position: absolute;
 right: 0px;
 border: 1px solid #000000;
 background-color: #ffffff;
}

この <DIV> は右端に接して表示されます。ほかにページの中身は無いのでスクロールバーは不要です。これを Mozilla は正しく配置します。

IE も正しく配置しますが、しかし同時に無用の右マージンを生成し、不必要な横スクロールバーを出現させます。

この <DIV>15ピクセルの余計な右マージンが生成される問題、その15ピクセルは、スクロールバー幅とまったく同じです。にも関わらず、どのような状況でスクロールバーがマージンの中に置かれるか理解するのは容易ではありません。このスクロールバースペースのまちがった扱いのバグの関係は、明らかになってはいません。

対策方法: right プロパティの値を 15px にして、右マージンを -15px に指定します。

div.container {
 height: 150px;
 width: 200px;
 position: absolute;
 right: 15px;
 margin-right: -15px;
 border: 1px solid #000000;
 background-color: #ffffff;
}

この結果は以下の通りです。

ほかのブラウザも IE と同じ挙動をするので、この対策方法はクロスブラウザ互換性にほとんど問題はありません(Windows 2000 環境での Mozilla を除く。たまに1ピクセルのわずかなマージンが出てしまいます)。

要素をブラウザウィンドウの底に配置する際にも同じバグが発生します。この場合、margin-bottom を -15px に指定しなければなりません。

スクロールバー下の margin

次の margin のバグは明らかにスクロールバーに関わるものです。不幸にも、常にではありませんがほとんどの場合このバグは表れます。1割から2割の確率で IE は以下のようなスタイルを正しく解釈しますが、リロードでまた変ってしまうでしょう。

バグ: IE はスクロールバー下の領域も表示部分に属しているとまちがって認識します。ページの中身は縦スクロールバーの下にはみでて、それによって不必要な横スクロールバーが表れます。

例:

body {
 margin: 0px;
 padding: 0px;
 font: 12px helvetica;
}

div.container {
 height: 150px;
 width: 100%;
 overflow: auto;
 -moz-box-sizing: border-box;
}

p {
 border: 1px solid #000000;
}

コンテナとなる <DIV> の高さを150ピクセル、幅を100%、overflow:auto とし、必要であればスクロールバーを表示するようにしました。-moz-box-sizing は Mozilla のボックスモデル問題を回避するためのものです。

特に指定しなければ、<P> 要素は常に使える限りの横幅 100% を取り、これらはコンテナ <DIV> の大きさにぴったり沿います。そして、ボックスにたくさんの細い P が含まれればスクロールバーが生じます。この時 P は、DIV の左マージンからスクロールバーの左端に沿うように、横幅を変化しなければなりません。

Mozilla では、そのスタイルは望んだ通りになります。

スクロールバーの出現に合わせてP要素の横幅は変化してフィットします。

しかし IE ではこんな表示になります。

P要素の横幅は正しく変化せず、横スクロールバーが生じます。

P は縦スクロールバーを突き抜けて横幅をコンテナの右端に沿わせます。これによってページの中身の一部は縦スクロールバーの下に隠れてしまい、IE は横スクロールバーをも作ることとなります。

対策方法: 基本的な解決法は、DIV に16ピクセルの padding-right を加えることです。

div.container {
 height: 150px;
 width: 100%;
 overflow: auto;
 -moz-box-sizing: border-box;
 padding-right: 16px;
}

でもこうしたら、他のブラウザにとって余計な padding を隠さなければなりません。幸いなことにコメント内のバックスラッシュによるハックで、padding-right の定義を MacIE のみに限定することができます。

div.container {
 height: 150px;
 width: 100%;
 overflow: auto;
 -moz-box-sizing: border-box;
 padding-right: 16px;
}

/* コメント内バックスラッシュのハック→ \*/

div.container {padding-right: 0px;}

/* ハック終わり */

これで、IE の padding-right は 16ピクセル、他のブラウザは0ピクセルとすることができました。P 要素はスクロールバーの左端に沿うようになり、DIV の横スクロールバーはもう必要ないので表示されません。

正しく表示されるようになりましたが、最初のPだけpaddingがおかしなことになりました。ブラウザウィンドウにも無用の横スクロールバーが。

残念なお知らせです。対策を施したことでふたつの新たな不必要な効果がでてきてしまいました。

ページ全体のスクロールバーの生じる原因は、また前記の「余分な15ピクセルのマージン」によるものです。margin-right のハックでこの問題は解決します。

div.container {
 height: 150px;
 width: 100%;
 overflow: auto;
 -moz-box-sizing: border-box;
 padding-right: 16px;
 margin-right: -15px;
}

そしてその結果です。

ページ全体の横スクロールバーは消えます。

不幸なことに、まだ最初の P の問題があります。最初のブロック要素は、マージンのバグに影響されません。スクリーンショットが示すように、最初の P だけは横スクロールバーの下に入っていないので、padding-right で不必要な隙間ができてしまうのです。しかしこの問題(の欠如)は一貫性がありません。ほとんどの場合、最初の P は正しく振る舞いますが、時々そうはなりません。

以下は Mac OS X 版の IE 5.2 向けの解決策です。OS 9 版では、まったく同じようには働きません。その策とは、<DIV> の最初の子要素に -16px の margin-right を与えることです。

div.container>:first-child {
 margin-right: -16px;
}

…そしてまたコメント内のバックスラッシュによるハックで他のブラウザ用のスタイルを上書きします。これで完璧な CSS になります。

div.container {
 height: 150px;
 width: 100%;
 overflow: auto;
 -moz-box-sizing: border-box;
 padding-right: 16px;
 margin-right: -15px;
}

div.container>:first-child {
 margin-right: -16px;
}

/* コメント内バックスラッシュのハック→ \*/

div.container {padding-right: 0px;}

div.container>:first-child {
 margin-right: 0px;
}

/* ハック終わり */

これで、通常はこのように解決されます。

Mozillaのスクリーンショットと同様のバグが無い状態になりました。

もう一度念押ししますと、これら一連のバグはやや気まぐれに起きます。この CSS ハックが全然効かない時もあります。

margin-bottom の逆継承

バグ: <DIV> 内に <P> を配置するときに、<DIV><P>margin-bottom の値を逆継承 します。

例:

div.container {
 height: 100px;
 width: 90%;
 border: 1px solid #000000;
 margin: 0px;
}

p {
 margin-top: 0px;
 font-size: 20px;
 border: 1px solid #000000;
}

このスタイルは以下のように表示されなければなりません(Mozilla でのレンダリング)。<DIV> の外にある最初の <P><DIV> のボーダーに接します。

しかし IE では、<DIV> は内部の最後の子要素の <P>margin-bottom の値を逆に継承して、不必要な隙間ができる原因になってしまいます。この時のマージン量は <P> の文字の大きさ次第です。

対策方法: P要素の margin-bottom を0ピクセルに指定する。

Overflow

overflow 宣言は、要素のはみ出た部分をどのように扱うかを定義します。要素が定められた幅と高さを持っていて、定義された領域に中身がおさまりきらないとき、3つの取り扱い方があります。

  1. overflow:visible で、中身はボックスからはみ出て表示されます。
  2. overflow:hidden で、ボックスにおさまらない中身は完全に隠れて、ユーザには利用できなくなります。
  3. overflow:auto で、ボックスは必要に応じてスクロールバーを表示します。このスタイルは前出のコードの例で用いました。

第4の値、overflow:scroll は、必要の有無に関わらず常にスクロールバーを表示します。ウェブ制作者はめったにこれを使用することはないでしょう。

はみ出た内容の範囲が切り抜かれない

バグ: 要素への overflow プロパティの値が visible 以外のとき、要素の中身が切り抜かれません。その代わり内容はページ上に存在し(見えないが)、スクロールバーを生じさせます。

例: 「隠れたmargin」で使用したコードの例にいくつか P要素を追加すると、不必要なスクロールバーが再び表れます。今回はページ全体の縦スクロールバーです。

<DIV> の余計な中身は、overflow:auto と宣言したにも関わらず、ページ全体にはみ出てスクロールバーを生じます。(最初の子要素の P が再びおかしくなっていることにも注意してください。これは非常に厄介なバグです。)

対策方法: body要素に overflow:hidden と指定してください。この対策により次のバグが現れるのは以下の通り。

body要素の overflow スタイルの飛び火

バグ: body要素の overflow プロパティの値を scroll もしくは hidden にすると、その後同じウィンドウやフレームに読み込んだページにスタイルが飛び火します。これは普通に起きますが、常に起きるわけではないことに注意してください。

対策方法: 同じフレームやウィンドウに表示されるページに、overflow:auto と明記することで初期値に戻します。

はみ出た要素の padding

バグ: overflow の値を visible 以外にした要素に padding スタイルを指定すると、padding 内のハイパーリンクがクリックできなくなります。

例:

.container {
 width: 200px;
 height: 200px;
 overflow: auto;
 padding: 50px;
}

このスタイルは、前述の無駄なスクロールバーのバグを除いては正しく描画されます。

しかし、padding 領域内にかぶるリンクはクリックで来ません。注意するのは、、padding は コンテナの見える範囲の端から算出されることです。。まだスクロールされていなくて padding-bottom が表示されていなくてもそうなります。

対策方法: ボックスの中身の要素にマージンをつけて、それを含む自身の padding を 0 に指定します。

結論

Mac 版 Internet Explorer 5 は、Microsoft 製のブラウザ中で最もウェブ標準互換性が高いにも関わらず、いくつかの CSS に関する問題点があります。残念ながら、これらのバグを根本的な原因と関連づけることはできず、従って特効薬を期待することもできません。

バグを回避する最良の方法は、すべてのサイトを IE 5 でテストすることです。しかしそれだけやっても、奇妙で不可解な現象が起こるでしょう。早く IE 6 がリリースされるよう望むしかありません。

関連リソース