ブラウザ互換性

ホームページの閲覧には様々なブラウザが使われています。 JavaScriptによる開発では古いバージョンも含めできるだけ多くのブラウザ(=ユーザ) に対応することが望まれます。

しかしマイナーなブラウザに合わせた結果、先進的な機能を使えなかったり或いは開発コストが増大するのも困ります。どこかでうまく線引きしましょう。
古いブラウザ=改革への抵抗勢力?!

ユーザ環境についての統計資料
Onestat.comの公開資料より

  • ブラウザ使用率:IE95.4%、Netscape2.5%、Mozilla1.6% (2003/7/28)

http://www.onestat.com/html/aboutus_pressbox23.html

  • OS使用率:Windows97.46%、Mac1.43%、Linux0.26% (2002/9/10)

http://www.onestat.com/html/aboutus_pressbox10.html

  • スクリーン解像度:SVGA(800x600)は31.7%、XGA(1024x768)以上は67%超 (2003/6/26)

http://www.onestat.com/html/aboutus_pressbox22.html

各ブラウザについて
IE4-6
IEは ビルド番号によって若干異なる場合もありますがバージョン間差異が小さいので対応はラクです。通常 IE4向けに実装した機能はIE5,IE5.5,IE6でもそのまま動きます。

通常、IEで対応しているOSはWindowsMacに限られます。 Windowsの普及率が97.46%に対しMacが1.43%であることを考えると殆どがWindowsIEです。

MacIEでは「document.all」が使えるなど Windows版向けに書かれたスクリプトの多くはそのまま使えます。しかしスタイルシートのfilter系機能や条件分岐コメントがサポート外など内部的には別物です。

Netscape6/7/Mozilla
Netscape6/7とMozilla及びその派生ブラウザは基本コードが共通しているため同じ記述で動作します。通常 Mozilla向けに書かれたJavaScriptはNetscape6+でも動作します。その逆も真です。

Mozillaで対応するOSはWindowsMacLinuxなど幅広いです。またIEとは異なり 稼動OSの違いによる動作の差異は少ないです。

行政など一部でLinuxを使おう!という動きが見られます。しかしLinuxではIEはありません。デフォルトのブラウザはMozillaになります。そのためMozilla系にも対応しておいた方がいいでしょう。

なお、次項のNetscape4.xと名前は共通しているものの 中身は別物です。例えばNS4向けのタグは動作しません。新しく書き直されておりどちらか言うとIEに近くなっています。

Netscape4.x
レイヤー、スタイルシート関係での様々なバグ、特殊な仕様のために対応コストは高いです。

【レイヤー処理が不安定】
NS4でレイヤーを扱うには 他のブラウザとは異なる独特の方法が必要です。また指定内容によっては予想外の動作をすることが多くこのサイトで扱っているような特殊なノウハウが必要です。

スタイルシート単独でも問題あり】
NS4にはレイヤー関係を除いても膨大なバグがあります。スタイルシートの指定が無視されたりテキストと画像が重なって本文が読めなくなるようなケースも簡単に発生してしまいます。
参考:Netscape4.xとスタイルシート(<HTML,CSSバグ&回避法リスト)

【では、どうするのか】
NS4の使用率は 0.6%だそうです(2003/07/28)。 2003/12/16の発表では 1.1% なので使用率は順調に?! 降下しています。

そろそろIE3やNS3と同じ扱いでもいいと思われます。

NS4に対応するのは大変なので内容が伝われば良しとするのが得策でしょう。スタイルシートでは「media=all」指定でNS4にスタイルを読ませないことが出来ます。
参考:ブラウザ別にスタイルシートを指定(<HTML,CSSバグ&回避法リスト)

同様にJavaScriptでは提供する機能がページ内容の理解に不要だったらNS4非対応でいいでしょう。

このサイトJavaScript@KeyNavi.netで扱ってる殆どの機能は特に断りのない限り NS4でも動作するようになっています。但しNS4に対応する場合はHTML側でも工夫が必要な場合があります。各ページの内容を参考にして下さい。

Opera
JavaScriptの開発から見た場合「document.all」が使える、UserAgentを詐称するなど特徴があります。デフォルトでは「Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.0 [en] 」などとなっており IEになりすましています。その他「Mozilla5.0/4.78/3.0」にユーザが切替できてしまうため CGI等でUserAgent値を利用する時は注意。まず文字列"Opera"の有無をチェックしましょう。

document.allが使えることから推察されるように JavaScriptについてIEMozillaで実装が異なる場合は IE側に合わせるケースが多いです。 JavaScriptでは「window.opera」の有無でUserAgentを使わずにOperaか否か分岐できます。

Opera6はそうでもないのですが Opera7はJavaScriptの実行速度が他のブラウザに比べ 格段に遅いという問題がありました。
参考:http://internet.watch.impress.co.jp/www/article/2003/0221/grey.htm

7.20では修正されたようです(2003/09/24)。またステータスバーへの出力(window.status="文字列") が動作しないバグも直っています。

Safari
MacではIEの開発が中止になったものの新しいブラウザ「Safari」が登場しています。 UserAgentが「Like Gecko」となっていることから推察されるように動作はMozilla系に近いです。

今のところ SafariJavaScriptのキーイベント処理に対応していません。このページ JavaScript@Keynavi.Netで扱っている KeyNavi内部の各個別関数は動作するもののキーを押しても動作しません。将来 対応したら そのままKeyNaviが動作するかも。

マウスイベントは大丈夫ですがページ全体に対するキーイベントをきちんと扱えない問題があります。その他、リンクに対するフォーカス(element.focus())の動作がおかしい、スクリーン上のマウス位置(event.screenX/Y)をブラウザ画面の左下隅から計算する などの問題があり修正が待たれます。

その他のブラウザ
IE3は外部JavaScriptファイルを読み込めません。 IE3非互換の記述は外部ファイルにすることができます。

いずれにせよこれらのブラウザでは大手サイトでもエラーが頻出します。 IE3,NS3以下をメインで使っている人は殆どいないので考慮外でいいでしょう。

互換性問題への対応方法

各ブラウザでの動作確認の工夫
上記で紹介した各ブラウザでの動作を各OSで確認するのは大変骨の折れる作業です。新たに追加した機能を 毎回 複数のPCを起動し確認するのは面倒なので1台のPCで複数のOSを起動できるVMwareVirtualPCなどを使うといいでしょう。
補足:WindowsIEは 基本的にOSと一体化しており1つのOSに1つのIEしか入りません。複数のバージョンでテストするには 個別にOSが必要です。

JavaScriptでのブラウザ分岐
互換性の高いスクリプトを書くには各ブラウザ毎に非互換の部分を分岐して別に処理します。

JavaScriptでの各ブラウザの判別は以下のようにして行います。「if(window.opera)」が真ならOpera、偽だけど「if(document.all)」が真ならIE、「if(document.addEventListener)」が真ならMozilla系などと絞り込んでいきます。稼動OSやその他細かい情報が必要な場合は 「navigator」属性から判定します。詳しくは ブラウザ判別:KL_IE/NS/OP/MZ 。

初期バージョンには注意
工業製品と同じく ブラウザでも初期バージョンには特有の問題が発生しやすいです。

Netscape6.0はUserAgentにMozillaのバージョン番号(rv)が含まれないなど Netscape6.1以上と異なる部分があります。

何かと問題の多いNetscape4.xでは バージョン4.05以下で特有のバグが幾つかあります。

ここまで古く且つ不安定なバージョンを使っているユーザはとても少ないと思われるので 通常は非対応でいいでしょう。

ブラウザ判別:KL_IE/NS/OP/MZ
ブラウザ判別を行うスクリプトです。

【ブラウザ判別「kl_identify()」<keynavi_ja.js】

KL_IDENTIFY_DONE=0;
function kl_identify(){

//複数回呼ばれた場合に同じコードを再実行しないよう対策
if(KL_IDENTIFY_DONE) return;

KL_IDENTIFY_DONE=1;

//ブラウザを大まかに IE,NS4,NS6,Opera系に分類します
while(1){
if(window.opera){
if(document.getElementById){ KL_OP6=1; break; }
}
else if(document.all){ KL_IE4=1; break; }
else if(kl_isns4_raw()){ KL_NS4=1; break; }
else if(document.addEventListener){ KL_NS6=1; break; }

KL_AVAIL=0; return;
}

//KeyNaviを利用可能なブラウザ(IE4+,NS4+,Opera6+,NS6+,Mozilla)では真に
KL_AVAIL=1;

var ua=navigator.userAgent;

//他の場所でUserAgentを参照する時に「navigator.userAgent」と書くと冗長なのでこれを利用
KL_UAGENT=ua;

//UserAgent値やdocument属性からバージョン情報を取得
//kl_getnum(s,h,defval)は文字列「h:数字」を含む文字列から数字部分を取得
//例:「MSIE6」「MSIE 6」「MSIE/6」「MSIE:6」の何れからも「6」を取得可
KL_IE5 =(KL_IE4 && document.getElementById); //IE5+
KL_IE55=(KL_IE5 && kl_getnum(ua,"MSIE",0)>=5.5); //IE5.5+
KL_IE6 =(KL_IE5 && kl_getnum(ua,"MSIE",0)>=6); //IE6+
KL_OP7 =(KL_OP6 && document.addEventListener); //Opera7+

//Netscape4.x、Mozilla系ブラウザでは細かいバージョン情報も取得しておく
if(KL_NS4){
KL_NSV=parseFloat(navigator.appVersion);
}
if(KL_NS6){
KL_MZV=kl_getnum(ua,"rv:",0);
KL_MZT=(!kl_match(ua,"Netscape") && KL_MZV>=1.2);
}


//UserAgent値からOS情報を取得
var win=kl_match(ua,"Windows");
var mac=kl_match(ua,"Mac");
var x11=kl_match(ua,"x11");
var sfr=kl_match(ua,"Safari");

//各ブラウザのOS情報を反映 (ユーザ数が多いWindows版を優先)
KL_IE4M=(KL_IE4 && !win && mac);
KL_IE4W=(KL_IE4 && !KL_IE4M);
KL_IE5W=(KL_IE5 && !KL_IE4M);

KL_NS4M=(KL_NS4 && !win && mac);
KL_NS4L=(KL_NS4 && !win && x11);
KL_NS4W=(KL_NS4 && !KL_NS4M && !KL_NS4L);

KL_NS6M=(KL_NS6 && !win && mac && !sfr);
KL_NS6S=(KL_NS6 && !win && !x11 && sfr);
KL_NS6L=(KL_NS6 && !win && x11);
KL_NS6W=(KL_NS6 && !KL_NS6M && !KL_NS6L && !KL_NS6S);
}

//Netscape4.xを判定 (「document.layers」とすると問題があるため別に判定関数を用意)
function kl_isns4_raw(){
if(!navigator.appName || !navigator.appVersion) return 0;
return (navigator.appName=="Netscape" &&
navigator.appVersion.indexOf("4.")==0)
}

上記「kl_identify()」の実行により各種定数が設定されます。「kl_identify()」は外部スクリプト指定「」内で実行されるため、この記述の後なら各定数を参照できます。

Note: Netscape4.xでは 「フレーム利用&外部スクリプト」の場合に「document.xxx」を参照するとJavaスクリプトの実行が止まるバグがあるのでブラウザ判定には「document.layers」を使いません。
参考:フレーム利用時に外部スクリプト実行中断(JavaScriptバグ&回避法リスト)

【各ブラウザ判別定数1:よく使うもの】
KL_IE4 IE4以上
KL_NS4 Netscape4.x
KL_NS6 Netscape6以上/Mozilla/Safari
KL_OP6 Opera6以上

上記定数を用いることによりブラウザ分岐処理を簡単に記述できます。
補足: JavaScriptスタイルシートの仕様、動作は大別して IE系、Netscape4.x系、Netscape6+&Mozilla系、Opera系に分かれます。 IE4-6.0では共通して「document.all」、 Netscape4.xでは「document.layers」、 Netscape6-7等Mozilla系では「document.addEventListener」が使えるなど互いに似通った特徴をもっています。

【各ブラウザ判別定数2:細かい動作を区別する場合に利用】
KL_IE5 IE5以上
KL_IE55 IE5.5以上
KL_IE6 IE6以上
KL_IE4W WinIE4以上
KL_IE4M MacIE4以上
KL_NS6W WinNS6以上
KL_NS6L LinuxNS6以上(その他Unix=x11系含む)
KL_NS6M MacNS6以上
KL_NS6S Safari
KL_OP7 Opera7以上
KL_MZV Mozillaのバージョン (「rv:」に続く文字列から算出、NS6+で利用)
KL_NSV Netscape4.xのバージョン
KL_UAGENT navigator.userAgentと同義

ブラウザの発展的な機能を使う場合、微妙に動作が異なることがあるため上記の定数を利用します。

例えば Netscape6+,Mozilla系ブラウザではUser-Agent文字列内の「rv:」に続くバージョン数に動作が依存するのでこちらで処理を分岐します。

【ブラウザ判定サンプルHTML:Copy&Paste】


アクセスしたブラウザの種類を判定し 結果を「alert()」で表示しています。

【参考:UserAgent値の例】
IE Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)
Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
Netscape4.x Mozilla/4.7 [ja] (Win98; U)
Mozilla/4.61 [ja] (X11; I; Linux 2.2 i686)
Netscape6+ Mozilla/5.0 (Windows; U; Win98; ja-JP; rv:0.9.4) Gecko/20011019 Netscape6/6.2
Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.0.2) Gecko/20021120 Netscape/7.01
Mozilla Mozilla/5.0 (X11; U; Linux i686; ja-JP; rv:0.9.6) Gecko/20011120
Opera Mozilla/4.0 (compatible; MSIE 5.0; Windows XP) Opera 6.03 [ja]
Mozilla/4.0 (compatible; MSIE 5.0; Linux 2.4.7-10 i686) Opera 6.1 [en]
Safari Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ja-jp) AppleWebKit/85 (KHTML, like Gecko) Safari/85