> ホーム > Web ページを作る > ブラウザを判別したい

ブラウザを判別したい

クライアントサイドの技術だけを使って

理想的にはブラウザのことなど考えずに情報を発信することができ、各ブラウザは自分の対応していない要素や技術について適切に処理してくれるといいのですが、現状のブラウザはバグ、仕様を含めそういう具合にはいきません。そこで何らかの方法でブラウザを判別して、各ブラウザに応じて処理を分ける、というテクニックが必要になります。

2002.02.20.

導入

JavaScript とか CSS とか、Web を作るときのクライアント側の技術を使う場合には、その技術に対応していないブラウザへの配慮をどうするか、というのが割とキモになります。で、ブラウザを判別するという作業というか行程というか過程が必要になるわけですが、問題はその方法です。

Web サーバとクライアントの間には裏で、わしはこれこれこういうサーバじゃ、うちはこれこれこういうブラウザじゃ、わしの扱っているデータはこれじゃ、うちはこれこれが扱えるぜよ、みたいなやりとりがあります。なので、この情報を利用すればどんな技術が使えるかというのはけっこう細かく切り分けられるのですが、本格的な切り分けにはどうしたってサーバサイドプログラミングが必要になります。でも、普通の人にはサーバをいじる権限もスキルもありません。CGI ならまぁ許可されているところもけっこうあるのですが、ここ hoops では許可されていないのでここでは扱いません。

そんなわけで取り上げるのはクライアントサイドの機能、テクニックに限定します。基本的にはコツさえ分かれば誰でも使えるものですね。

JavaScript を使う

よくある方法として JavaScript を使うという方法があります。まぁブラウザから利用できるスクリプト言語はこれだけに限らないのですが、できるだけプラットフォームに依存しないようにと考えると現実的には JavaScript とそれに類するものを使うでしょう。

で、最近のたいていのブラウザに実装されている navigator.userAgent を利用します。これはもともとサーバに渡す HTTP_USER_AGENT という値をそのまま JavaScript で利用しているようです。(ほかにもブラウザの判別に使えるプロパティ、ブラウザからサーバに渡る情報はいくつかあります。)

具体的には navigator.userAgent は文字列を返すので、これを判別したいブラウザの名前と比較するわけです。

具体的な判別の一例

実際、説教講座ではこんな感じで判別してます。(2002.02.現在)正規表現を使っているのはなんとなく好みです。その方が短く書けそうだし。

なんて感じで使ってます。あんまりきれいじゃないかも。

cat_version() でちょっと変なことしてます。具体的には iCab 対策で作ったんですけど、2.7.1 という文字列を 2.71 にする、つまり2個目以降のピリオドで分割された数字を、ピリオドが1つの普通の‘数値’になるようにくっつけちゃうという処理をしています。こうしておかないと数値として比較できないんで。

var NN4 = document.layers;
browser = navigator.userAgent;

// iCab
if ( browser.match( /iCab[^0-9a-zA-Z]*([0-9.]+)/ ) ) {
  var iCab = cat_version( RegExp.$1 )-0;
}

// めちゃ古いブラウザ
var vo_mozilla = browser.match( /$Mozilla\/[0-3]/ );

// IE 4.x 以前
if ( browser.match( /MSIE[^0-9a-zA-Z]*([0-9.]+[^;])/i ) ) {
  var IE = cat_version( RegExp.$1 )-0;
}

// Opera
if ( browser.match( /Opera[^0-9a-zA-Z]*([0-9.]+)[^;]/ ) ) {
  var Opera = cat_version( RegExp.$1 )-0;
}

PRODUCT = navigator.product;
if ( PRODUCT ) {
  var N6 = PRODUCT.match("Gecko");
}

function layer_ng() {
  if ( NN4 || vo_mozilla || IE < 5 || iCab <= 2.71 || Opera <= 6.0 ) {
    return true;
  } else {
    return false;
  }
}

function cat_version( sep_version ) {
  if ( sep_version.match( /([0-9^.]+)(\.)([0-9^.]+)(\.)([0-9]+)/ ) ) {
    return cat_version( RegExp.$1+RegExp.$2+RegExp.$3+RegExp.$5 );
  } else {
    return sep_version;
  }
}

どういう理由で判別するかによって判別方法は変わってくると思うのですが、バージョンごとの実装が分かっているのであれば、この方法は汎用性があり、なおかつ楽じゃないかと思います。(Netscape 4 の部分は手抜きですね。PNG 対応の判別をしようと思ったら他のブラウザと同じようにバージョン番号をきちっと取得する必要があります。)

JavaScript に対応した比較的マイナーなブラウザ

IE や Netscape の情報はだいたいどこにでもあるのでここではちょいマイナーなものだけ。つっても日本語の通らないやつとか UNIX 用のものは入ってません。ま、いずれもその筋では有名なものばかりですが。

JavaScriptで取得できるブラウザ情報の一部
iCab 2.7.1 68k Mozilla/4.5 (compatible; iCab 2.7.1; Macintosh; I; 68K)
Acrobat 5 WebCapture(Win) Mozilla/3.0 (compatible; WebCapture 2.0; Windows)
Opera 6.0(Win2k) Opera/6.0 (Windows 2000; U) [ja]
Mozilla/5.0 (Windows 2000; U) Opera 6.0 [ja]
Mozilla/4.0 (compatible; MSIE 5.0; Windows 2000) Opera 6.0 [ja]
navigator.product
(Geckoエンジン搭載ブラウザ)
Gecko

その他の情報

その他っちゅーか、こっちの方がはるかに頼りになります。

ブラウザのバグ、仕様を利用する

CSS の対応具合を見分けるためにブラウザの判別をしたい場合があります。このブラウザのこれこれのバージョンまではこの辺がまともに対応していない、という情報がいろいろあるのですが、いかんせんそういう細かい情報を活かすためにはクライアントサイドなりサーバサイドなりでバージョン番号を判別するためのプログラムを動かす必要があります。

しかしサーバサイドプログラミングはこのページの趣旨から外れるので除外、そして、JavaScript はオフにしていたら終わり、つまり気休め程度にしかならないのでこれもダメ。

じゃあどうするかっていうと、まさにその「ブラウザが対応していない」という事実を利用するのです。これがブラウザのバグを利用する、という意味です。

CSS対応の不備を利用する

特に問題の多い IE 3, Netscape 4 を外すためによく使われます。

ブラウザよく使われるテクニック
IE 3
  • 外部スタイルシートを複数用意し、最後に空っぽのファイルを指定する
  • @media宣言の中にスタイルを記述
  • @import で別なファイルにスタイルシートを記述
Netscape 4
  • @media宣言の中にスタイルを記述
  • @import で別なファイルにスタイルシートを記述

@media を使ったブラウザの判別は手っ取り早くて便利です。この方法だけで

などのブラウザにスタイルが適用されないようにすることが可能です。ただし、CSS の対応具合の比較的いい Mac版 IE 5 がなぜか対応していないので、せっかくのスタイルが反映されなくなってしまいます。これはちょっと残念。(Opera についてはよー知りません。あちこちの実験結果とか情報を漁ってもあんまり自分のほしい情報がないんですね。どうにか position 周りのバグを回避したいんですが。)

@import は書き方一つで対応しているブラウザがコロコロ変わるので使うときはちょっと注意が必要です。(ま、IE 3 や Netscape 4 では問答無用で非対応ですけど。)

IE 3 は line-height: 1.5em; なんかの見易さのための行間調整がすべてアダになるので、(対応していない単位をすべて px 単位に置き換えてしまうので)IE 3 は最初っから除外する方法が簡単でいいでしょう。JavaScript の実装もかなりひどいものですし、IE 3 ユーザーは JavaScript も CSS もオフにしているとは思いますが、念のため。IE 3 狙い撃ちは複数の外部スタイルシートを指定して、最後にダミーのファイルを指定する方法が簡単です。IE 3 は最後のスタイルシートしか適用してくれないからです。

Netscape 4 は font-family: に日本語のフォント名を指定するなど、対応していない値を指定するとその要素が表示されなくなっちゃうというとんでもないバグがあったりするので、この辺の指定も @import や @media を使って Netscape 4 を外すようにした方がいいでしょう。こちらで確認したものでは

なんて辺りがちょっと致命的かなという感じです。

参考

JavaScript, Refresh 非対応を利用する

Lynx 2.8.1(他のバージョンのことはよく知らない)や i-mode, ezweb 端末は JavaScript にもページの自動リフレッシュにも対応していないのでこれを利用して判別できます。具体的には

  1. トップページを携帯(テキストブラウザ)用にする
  2. JavaScript や <meta http-equiv="refresh" > を使って別のページに自動的にジャンプする
  3. 対応しているブラウザでは指定したページにジャンプし、対応していないブラウザはトップページが表示されたままになる
  4. こうしてブラウザを判別して、あとは携帯・テキストブラウザ用(メディアタイプで言うと tty や handheld、tv なんか?)、PC用で別々にサイトを構築していく

という感じでしょうか。サーバサイドで判別すればもっといろんなことができますが、クライアントサイドの技術だけに頼るのであればこの辺で精一杯って感じですね。

でもテキストブラウザは今さら機能拡張路線を取るとは思えないけど、携帯電話がいつ refresh や JavaScript に対応するとも限らないし、ちょっと不安ではあります。とりあえず確認した機種を以下に

JavaScript, refresh に対応していないブラウザの HTTP_USER_AGENT
Lynx 2.8.1dev5 日本語化Win32版Mozilla/3.01 (compatible;)
HITACHI C3001H(cdmaOne + GPS)KDDI-HI21UP.Browser/6.0.2.273 (GUI) MMP/1.1

Lynx の情報はほとんど全然参考になりませんね(^^;

i-mode は refresh に対応していないそうですが、自分で持っていないので確認できません。J-PHONE は J-Sky とか言い始める前は使っていたのですが、これも今は分かりません。

PC用のテキストブラウザはともかく、携帯電話の場合はページ容量の問題もあるので、できるだけ分けて作った方が楽でしょうね。その際、「同じ内容なのに別々のマークアップをしなきゃいかんのか」と思うかもしれませんが、その辺は適当にツールを使うしかないでしょうねぇ。携帯に対応したホームページ作成ソフトもいくつかあるし、自分なりにマークアップにルールを作ってしまえば Perl などのスクリプト言語でだいたい変換できると思います。

ゆっても、こういう無料スペースでは広告の都合があるので携帯用のページはここに作れという指定がある場合もあります。