Mac の食えない野郎ども

〜 Mac版 IE5 の傾向と対策 〜

Mac版 IE4.5 は知る人ぞ知る JavaScript 泣かせのアブナイブラウザですが、 IE5 はどうかと言うと IE4.5 の多くの致命的バグを修正したブラウザです...
が、同じくらい多くのいただけない仕掛けを作り込んだブラウザでもあります。

そこで、ここではスクリプトの動作上致命的になりやすい IE5 の問題の紹介と、 できればその対策を採り上げたいと思います。

** ここで挙げている内容は、たまたま Mac を借りた時に調べたことを基にしています。 ですから、この項目は実際と異なってしまっているものもあるかもしれません。
#> 間違っているからといって、確認することすらできません(笑)。

#> Mac欲しいなぁ〜、誰かくれないかなぁ... f(^^;


目 次

IE5.12 のバージョン
う〜む、まさかね〜...
DOCTYPEの恐怖
IE5.12 っていろいろとやってくれますねー
ウィンドウのサイズ
ウィンドウのサイズを取得したいんだけど...
offsetLeft と offsetTop
こんなのあり? IE4.5 の不具合修正を補ってあまりある致命的問題
レイアの生成 と offsetTop
IE のバグは予測不可能ってことかな f(笑;
レイアの高さ( offsetHeight )
これ、ワザと? ...じゃないよなぁ...
レイアを直接生成する
IE4.5 で動かなかった insertAdjacentHTML が、IE5 で殆ど動かないメソッドに改善された(笑)
IE5.12 の innerHTML問題
IE5.12 では insertAdjacentHTML が動くようになったけど...
レイア内のブロック要素
IE5.12 の innerHTML 問題の核心?
フォント関連属性の不思議
属性を変更したつもりなのに...
IFRAME 内のドキュメントサイズ
代表的な改悪の例みたい
ネストされたレイアのパフォーマンス
IE5のパフォーマンスはお話にならん
クリップ領域内の子レイア
レイアはネストするなってことかなぁ
忘れられたスクロールバー
これ、この Tips集のトップページのこと。苦情のメールが来たもんで(笑)
ハイパーリンクの範囲
うう。これは JavaScript とは関係ないか(笑)
FORMのテキスト入力域
ん〜。ひょっとすると「ことえり」の問題かも...

IE5.12 のバージョン

IE5.12(OS X)の appVersion, userAgent は以下の値が設定されています。

navigator property
appVersion4.0(compatible; MSIE 5.0; Macintosh; I; PPC)
userAgentMozilla/4.0(compatible; MSIE 5.12; Mac_PowerPC)

おやおや、appVersion と userAgent では自分自身に関する意見が異なるようです(笑)

つまり、ブラウザが 5.12 かどうかを判定するためには appVersion ではなく userAgent プロパティで判断しなければならないようです

#> う〜む、ブラウザのバージョンだけでなく OS や CPU の表記も異なるですね〜

... ひょっとして、修正過程で userAgent の文字列を変更したのに appVersion の方を修正することを忘れたのでしょうか?

... まさかね〜、確認すれば一発でわかる話だし... (笑)


DOCTYPEの恐怖

IE6(Win版)では DOCTYPE宣言の書き方によってスタイルシートの解釈を従来方式か W3C準拠かを切り替える仕様を入れてしまいました

IE5.12 はこの方式を採り入れることにしたのか、DOCTYPE宣言に URL を指定すると いろいろとやってくれるようです(笑)

例えば、

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">

こんな記述をしようものなら簡単に不幸のどん底にたたき込まれます

#> まあ、DOCTYPE宣言に URL を指定しなくっても border 幅を 0 に指定していたり、 厳密なレイアウトが必要でなければ対して問題にはならないけど、 最近更新したページは DOCTYPE宣言に URL を記述しているんで、どーしよう... (-_-;


ウィンドウのサイズ

ブラウザのウィンドウに合わせてレイアウトしたい時にはウィンドウサイズが必要になります。

IE ではウィンドウそのものに関する情報はないため body オブジェクトのプロパティで代用します。

しかし、これらの値はよく見ると実にいい加減だったりします(笑)。

IE5.12 では body.clientWidth/Height は body.offsetWidth/Height と同じ値になりますし、 スタイルシートに関する描画はルールは W3C準拠に見えますが、 これらの幅や高さは従来どおりだったりします(笑)。

フレーム構成の場合の全体( frameset )のサイズは offsetWidth/Height のみ設定されるようです(*1)。

*1 まあ、frameset なんで client領域の概念がないのは理解できますが Win版とは異なる動作( 実は Win版 IE6 では offsetWidth と clientWidth は異なる値になる ) になりますし、 それ以上に bodyタグがないのに bodyオブジェクトから情報を取得するのもヘンですねぇ(笑)

もし、あなたのご使用のブラウザが Mac OS X版IE5.12 なら 実際にこちらで確認することができます。


offsetLeft と offsetTop

IE5 は座標計算の基本的な部分に致命的な問題をいくつか抱えています。
レイアオブジェクトの offsetLeft, offsetTop もその問題の1つです。

レイアオブジェクトのこれらのプロパティはスタイルシートで位置を指定せず、 ブラウザのフロー制御によりレイアウトされたレイアの位置を知るためによく使用されます。

IE5 の問題はこれらのプロパティの値が実際の位置とは異なる値を示すことにあります。 初期状態でのページなら多分実際の値より( 10,15 )だけ小さな値になると思います。

これは、style オブジェクトの left, top プロパティの座標系の原点がウィンドウの左上コーナ であるのに対して、offsetLeft, offsetTop はページのマージンを除いた領域の左上コーナから 計算しているらしいのです。

なら、この問題の対策は offsetLeft + document.body.leftMargin で済みそうに思われますが、 実際にはそれではうまくいきません。
つまり、BODY のマージンの指定方法には BODY タグで指定する leftmargin, topmargin のほかに、 スタイルシートやインラインスタイルで定義できます。

そして、これらの値は互いに矛盾する指定もできます。
これでは単純な式で補正することは難しい問題になります。

結局、最も簡単な方法はスタイルシートで BODY のマージン( margin-left, margin-top )を 共に "0" にしてしまうことでしょう ( これだと条件付きにはなりますが補正の必要はなくなります )。

// Mac だけなら
if(document.all && document.getElementById
   && navigator.userAgent.indexOf('Mac')!=-1){
  document.write(
     '<style type="text/css">¥n'
    +'BODY { margin:0px; }¥n'
    +'<¥/style>¥n'
    );
}

もし、あなたのご使用のブラウザが Mac版IE5 なら 実際にこちらで確認することができます。

*1 まあ、再利用可能なスクリプトである必要がなければ、 ブラウザを判別して補正することはできますが... f(^^;


レイアの生成 と offsetTop

単純な HTML では気がつかないかもしれませんが、 IE 5.12 では static なブロックタグ( H1 とか P タグ )の高さが不自然に大きくなるものがあり、 ページのレイアウトに苦しむ場合があります。

この高さはボーダ枠の下に余分な間隙ができるもので、 この間隙の高さはタグの記述の仕方によりまちまちのようです

#> これだけならスタイルシートの実装が貧弱な NN4 にも言えることなんですけどねぇ

困ったことに、このようなタグを定義した場所に依り、onLoad イベント以降にレイアを生成すると offsetTop の値に間違った値が設定される場合があるようです。

これは生成したレイアのみならず、HTML と スタイルシートで定義したレイアの offsetTop までも、 この操作により異なった値( 正確には余分な間隙の高さ分小さい値 )になります。

つまり、レイア生成後にレイアの位置を取得しようとしたり、offset値を基準に移動しようとすると 正常に動作しないことになります

一応、問題となるブロックタグを DIVタグ で包み込めば回避できそうですが、 確実かどうか今ひとつ判断できません。

できれば、必要な情報はレイアを生成する前に全て取得しておき、 生成後は offsetTop を参照せずに位置計算をするようにした方が無難かもしれません。

もし、あなたのご使用のブラウザが Mac OS X版 IE5.12 なら 実際にこちら で確認することができます。


レイアの高さ( offsetHeight )

スタイルシートでの width,height の値は IE ではレイアを生成する際の参考にされ、 実際のサイズはレイアの場合 offsetWidth,offsetHeight に設定されます。

しかし、Mac版 IE5 では offsetHeight の値はスタイルシートでの指定がそのまま設定されます。

対策としては正しい値をスタイルシートで設定するか、指定に意味がなく必要な高さに調整したい だけなら height の指定を省略します。スタイルシートで値が設定されていなければ生成したレイ アのサイズが正しく設定されます。

もし、あなたのご使用のブラウザが Mac版IE5 なら 実際にこちらで確認することができます。

*1 正しく設定されないのは offsetHeight のみで offsetWidth は正しく動作します。

また、これは確証がないのですが、間違った height を指定しても描画はされていますが、 height で指定した値が見かけのレイアサイズより小さい場合には、 レイアを移動したりすると描画抜けの原因にもなっているようです。


レイアを直接生成する

onLoad イベント以降でページに HTML要素を追加しようとするなら insertAdjacentHTML を使用します。

document.body.insertAdjacentHTML(
    'BeforeEnd',
    '<div class="d" id="d1"><¥/div>');

また、同様に生成したレイア内に文字列などの HTML を入れるにも insertAdjacentHTML を使用します。

document.all('d1').insertAdjacentHTML(
    'BeforeEnd',
    '<p>Hello!<¥/p>');

Mac版 IE5 で上記2つの命令を複数実行すると、 以前に生成した全てのレイアのサイズが変化します。
これは、どうやら最初のレイアの生成時 HTML の解釈を失敗しているために発生するようです。

例えば、最初のレイア生成の DIVタグ の閉じタグの後に空白( 半角スペース )を 追加すれば正常に動作します。

document.body.insertAdjacentHTML(
    'BeforeEnd',
    '<div class="d" id="d1"><¥/div> ');
document.all('d1').insertAdjacentHTML(
    'BeforeEnd',
    '<p>Hello!<¥/p>');
      :

もし、あなたのご使用のブラウザが Mac版IE5 なら 実際にこちらで確認することができます。

*1 但し、これやると、レイアの内容とレイアサイズが一致しなくなるので、 ちょっと考えちゃいますけど... f(^^;

*2 どうやらこの問題は IE5.12(OS X) では修正されたようです


IE5.12 の innerHTML問題

Mac版 IE の innerHTML,insertAdjacentHTML は鬼門のようです(爆)。

今までまともに動作しなかった insertAdjacentHTML メソッドが動作するようになったのは 喜ばしいこと(笑)ですが、こんどは代わりに innerHTML が動作しなくなったようです。

例えば次のような HTML がある場合

<style type="text/css"><!--
.t{ position:absolute; }
--></style>
    :
<p> ... </p>
<div class="t" id="t1"> ... <div>
<p> ... </p>
    :
<div class="t" id="t2"> ... <div>
</body><html>

"t1" の DIV要素の innerHTML を書き換えると DIV要素 "t1" の横幅がウィンドウサイズにまで拡張されてしまいます(*1)。
また高さは謎な高さになります。

*1 width が設定されている場合は指定した width で文字列を折り返しますが、 やはり要素の幅は伸長されます。
また、DIV要素 "t2" の方は拡張されません

色々とテストしてみると position:absolute な要素を absolute でない要素の途中で定義した場合に幅が拡張され(*2)、 高さは定義した要素の次の要素に依存して変化します。

*2 これは類推ですが、absolute な要素であっても中に Pタグなどのブロック要素が含まれると ウィンドウ幅になる問題があり、 innerHTML に設定する際、以降に absolute でない要素があると 暗黙のブロックタグの補完が行われた結果の現象のようです

因みに、DIV要素の代わりに P要素にした場合にはこのような現象は発生しません
#> これじゃ CrossBrowser にはなりませんけどねぇ... f(^^;

もし、あなたのブラウザが OS X版 IE5.12 なら こちらで確認することができます。


レイア内のブロック要素

「IE5.12 の innerHTML問題」でも少し記述しましたが レイア(absolute なDIV要素)内の HTML にブロック要素があると position 指定を忘れた描画をするようです

具体的には、レイアの幅は本来必要なサイズに調整される筈ですが P,DIV,FORM など(*1)ブロック要素があると bodyブロック内にブロック要素を記述した場合と 同様な幅に調整(笑)されます

*1 この他には HR タグでも発生します

また、不思議なことに TABLE,FORM があるレイアにインライン要素で置き換えても 同様な現象になるようです

もし、あなたのブラウザが OS X版 IE5.12 なら こちらで確認することができます。


フォント関連属性の不思議

DHTML のスクリプトを作成する場合、 ある要素に含まれるテキストの属性を変える場面は色々とあります

例えば、ズーム効果を出すためにフォントサイズを動的に変更したり、 マウスなどの操作に伴ってフォントの形式を変えたりといった場合があります

しかし、IE5.12 では旨くいきません
細かく言うと動作しないのは position:absolute な要素に直接含まれるテキストのみで、 absolute 指定をしない子要素に含まれるテキストには反映される(*1)ようです
また、反映されない属性は font-size, font-weight, font-style があり、 font-family(*2), font-variant などは有効なようです

*1 つまり、position:absolute な要素の子に position:absolute なブロック要素(DIVなど)でも つければ回避できますけどねぇ...

その他の回避策としては属性を変更した後、 該当の要素の内容をもう一度書き出せば反映されますが、 これはこれで別の問題があるんでお勧めできません(-_-;

*2 反映されると言っても font-family は設定通りの書体にはならないようですけど(笑)

もし、あなたのご使用のブラウザが Mac版 IE5.12 なら 実際にこちらで確認することができます。


IFRAME 内のドキュメントサイズ

IFRAME で表示している HTML のドキュメントサイズは document.body.scrollWidth/scrollHeight で取得できますが、Mac版 IE5 では IFRAME 自体のサイズが設定されています。

この問題は実は scrollWidth が offsetWidth と逆に設定されていることと scrollHeight が offsetHeight と同じ値が設定されているためにこのようになります。
必要ならプラットフォーム・ブラウザ・バージョンの判定をして scrollWidth, offsetWidth については逆に読み替えれば良いのですが、scrollHeight に関しては取得できません。
固定値で扱うしかないようです(泣)。

もし、あなたのご使用のブラウザが Mac版IE5 なら 実際にこちらで確認することができます。

*1 IE4.5 では読み替えるだけなのに、これじゃあ前より悪い...

*2 IE5.12(OS X)ではこの問題は改善されて scrollHeight は offsetHeight に正しく設定され、 代わりに scrollWidth の値が取得できなくなったようです(爆)


ネストされたレイアのパフォーマンス

Mac版 IE5 は IE4.5 と比較して全体的に実行動作が重くなっています。

下表は Mac版 NN4.7, IE4.5, IE5 で測定した結果です。

*1 但し、IE4.5 の測定値は IE4.5 の各種致命的バグのために、 値がどの程度正しいかは疑わしいので参考としてです。

ブラウザ項目1234
NN4.7 移動(縦横)1.851.933.331.92
移動(横) 1.041.032.291.00
表示切替 1.411.483.601.47
IE4.5 移動(縦横)19.5019.8019.6219.49
移動(横) 10.2610.3710.3410.26
表示切替 6.957.0877.446.53
IE5 移動(縦横)22.7824.25155.1122.65
移動(横) 11.1811.26117.3811.26
表示切替 7.637.76106.737.70
測定は「怪談! Cross Browser」の「レイアの表示制御手法」で行ったのと同種のテストで、 横軸の番号は以下の意味です。

1. 5×5のタイル状に並べたレイアの1つを対象にした場合
2. レイアの子として5×5のタイル状に並べた子レイアの1つを対象にした場合
3. 5×5のタイル状に並べたレイアを子に持つ親のレイアを対象にした場合
4. 5×5の一部が重なるレイアの1つを対象にした場合

*1 数値は測定値の最小のものを 1.0 とした比率です。

IE は NN と比較して移動処理で 10 〜 13 倍程度、表示処理で 4 〜 5 倍程度の処理時間の 違いがあります。 中でも IE5 はネストされた( 入れ子になった )レイアの親レイアに対する操作が 子レイアの数に比例して処理時間がかかるため( この傾向は Win版でも同じ )、 比較にならないほど遅い結果( なんと 30 〜 50倍 )となっています。


忘れられたスクロールバー

フレーム構成のページで BODY属性に scroll="no" を指定したページの後に 通常のページ( scroll="no" を指定していないページ )を表示しても スクロールバーは表示されません。

もし、あなたのご使用のブラウザが Mac版IE5 なら 実際にこちらで確認することができます。

*1 一応、scroll="no" を指定しているページで onUnload イベントで元に戻してやると なんとかなるんですが、やりたくないですね〜。
かといって、全てのページに scroll 指定をするのもね〜...


ハイパーリンクの範囲

ハイパーリンクを含む文章でリンク部分が文章の最後にあり、 リンク部分で改行されると、折り返したリンクの右側の領域に マウス受付け範囲が伸長されるたりします。

*1 これは JavaScript には関係ないけど、おまけ(笑)。


FORMのテキスト入力域

通常に FORM を使用する分にはよいのですが、レイア内のFORMを配置した場合、 レイアを移動すると FORM内の入力域( TEXTAREA, TEXT )はお話になりません。

つまり、表示域と入力位置が生き別れになります。 f(^^;

*1 この現象はどのブラウザでも発生するので、 ひょっとすると「ことえり」の問題なのかもしれません。
アタシは Mac に詳しくないので...


Copyright(c) 2000 - 2002 ShinSoft. All rights reserved.