Note

スタイルシート、JavaScript、DOM、ブラウザ判別、PHP 等ウェブ制作関連の各種情報



Web Design Creative Note : The Trap of Web Design

ブラウザ判別とスタイルシートのカスケード

最近の自分の手法

2005-01-01 にちょっと追記しました。勿体ないから書かないでいた最近よくやってる手法。PHP や .htaccess が使えるサーバーであることが前提ですが、いくつものスタイルシートカスケードを必要としません。今後はソッチにどんどん移行予定。

各種手法

ブラウザ判別のやり方はいろいろあって、状況で使いわけます。

あるブラウザに専用のスタイルシートをリンク(カスケード)したい場合、ということだったら、

  1. スタイルシートのブラウザ別対応状況から、非対応プロパティ等を使ってなんとかする。
  2. なんらかのサーバーサイドスクリプトがつかえるなら、そのスクリプトでユーザーエージェントを取得し、それに応じたリンク要素を書き出す。(CGI、SSI、PHP等)
  3. スタイルシート自体をサーバーサイド処理送出する
  4. JavaScriptでユーザーエージェントを取得し、それに応じたリンク要素を書き出す。
  5. JavaScriptでユーザーエージェントを取得し、それに応じたスタイルシート記述を返す。

自分の場合は、ここんとこ標準準拠仕様で記述していて、

というカスケード状況が基本です。あとはページ別に専用設定シートが増えたり、alternate シート作って切り替え可能にしたりもやってます。Opera、Mozilla 専用というのも考えることはありますが、JavaScript 絡みのシカケを使っているためというのが多く、そういう場合は JavaScript で制御します。また、増えるばかりでなくて、まとめれたらまとめるので減ってることもある。だってホントは少ないほうが管理しやすいですもん。

以下、JavaScript の場合も同様なんですが、いっぱいカスケードしても、ブラウザ自体の判別はだいたい上記でわかるように、IEの5 以降が分けれたらなんとかなると勝手に決めてます。IE4 はネットスケープ4 と一緒にケられまして全くカスケードしていない筈ですが、最近殆どチェックしてないから知らない(笑)

スタイルシートのブラウザ別対応状況から、非対応プロパティ等を使ってなんとかする

つまり普通記述して、もしそのブラウザが非対応のプロパティを使っても、無視されるので、そのままで良しというやつですね。これを逆に考えて例えば、@import はネットスケープ4 が非対応なので、それで取り込んだスタイルシートはネットスケープ4 以外で反映される、ちゅうやつです。ただ、バグなんだか仕様なんだかよく分からないものもあって、コンマなんぼのバージョン違いで異なるようなヤツは簡単に使えないです。

最近は以下の表といつもニラメッコして、なるべく複数スタイルシートを使わずに済ますようにするのが「最先端」(笑)

おかげさまで、よく使うのが、

...と、ほぼ自由自在になってきたような気がします。

問題は、なんでも振り分けられるだろうと、ついつい、やりすぎてしまって、結局記述が複雑で見づらくなることだったり。

昨今の様々な情報のおかげで自分の手法もだんだん落ち着きつつあります。

サーバーサイドスクリプトでユーザーエージェントを取得し、それに応じたリンク要素を書き出す

サーバー環境によりますが、確実です。非対応プロパティは、常に必要な箇所があって使うし、それだけで確実なブラウザ判別まではできません。上記のオレ様の環境では、基本シートの後にIE用をリンク(カスケード)して、必要な箇所だけ上書きします。シート内に複数の判別指定をいれるのと、ブラウザ専用シートを作っておいて、必要時にそのシートに記述するのと、ドッチが楽かは作るひとによって違うでしょうし。

SSIの場合。今はこのサイトでは使ってません(PHP にしちゃったから)が、PHP はだめだけど、CGI/SSI は使えるサーバーの時に。

<!--#set var="UA" value="$HTTP_USER_AGENT" -->
<!--#if expr="($UA = /Windows/) && ($UA = /MSIE/)" -->
<!--#if expr="$UA = /MSIE 6./" -->
<link rel="stylesheet" type="text/css" href="./wie6.css" charset="Shift_JIS" />
<!--#endif -->
<!--#if expr="$UA = /MSIE 5./" -->
<!--#if expr="$UA = /MSIE 5.5/" -->
<link rel="stylesheet" type="text/css" href="./wie55.css" charset="Shift_JIS" />
<!--#else -->
<link rel="stylesheet" type="text/css" href="./wie5.css" charset="Shift_JIS" />
<!--#endif -->
<!--#endif -->
<!--#endif -->

正規表現はややこしいのは見ていると頭がいたくなるんですが、まぁこの程度だったらね。

改行等は排除したほうがよいです。関係ないブラウザに空き行できちゃうから。

PHPの場合。 SSIよっかは見やすいか。Perl はどーしよう。面倒になってきた。ほとんどおんなじだし。

<?php
$ua = $_SERVER['HTTP_USER_AGENT'];
if ((ereg("Windows",$ua) > 0) && (ereg("MSIE",$ua) > 0)) {
 if (ereg("MSIE 6.",$ua) > 0) {
  echo '<link rel="stylesheet" type="text/css" href="./wie6.css" charset="Shift_JIS" />';
 }
 if (ereg("MSIE 5.",$ua) > 0) {
  if (ereg("MSIE 5.5",$ua) > 0) {
   echo '<link rel="stylesheet" type="text/css" href="./wie55.css" charset="Shift_JIS" />';
  } else {
   echo '<link rel="stylesheet" type="text/css" href="./wie5.css" charset="Shift_JIS" />';
  }
 }
}
?>
get_browser() を使う

PHP のリフェレンスみてたら、get_browser() ちゅう関数があるんで、なんだこれ?と調べたら、php.ini で、browscap.ini という設定ファイルを指定していたら、ブラウザ情報を返すものだとわかった。

<?php
$brschek = "<ul>";
$arybrs = get_browser();
foreach ($arybrs as $key=>$val){
 $brschek .= "<li>".$key." : ".$val."</li>"."\n";
}
$brschek .= "</ul>";
echo $brschek;
?>

もし、サーバー側で動作するように設定されていたら、以下のように送出されます。(未設定では Warning: get_browser(): browscap ini directive not set....)

※以下は実際にこのページで動作させたものではないです。

で、JavaScript動作可能かどうか等が、サーバーサイドで判別できるので、こりゃ便利、と思ったら、実際にアクセスしているユーザーの設定環境を返すのではなく、ユーザーエージェントを取得し、それに対応する browscap.ini に記載された内容を返すだけで、例えば、ユーザー側で JavaScript をオフにいていても 1 を返す。

ま、だから「使えない」ということはなく、JavaScript のオンオフをサーバーサイドで調べなきゃならないという事をしないにこしたことはないので、やるべき内容によってはこの判別手法もアリだなぁ、ということでした。

get_browser(); を動作させるには?
ネット上で配布されている、browscap.ini というファイルを手にいれて、サーバーのどっかにいれる
php.ini に、[browscap] という設定項目があるので、そこに browscap.ini への絶対パスを記述する

browscap.ini は、デフォルトではいっているものではないらしく、また、ブラウザが増えたりすれば書き換える必要がある「静的ファイル」で、検索すると、配布されているものをダウンロードできる。それみて書式わかれば、自分で書き換えて更新できるけど、サーバー管理者しかできないし、おそらく、逐次更新しないと、ユーザー側から「更新しろ」といわれたりする場合があるわけで、これは管理者にとっては面倒だったりするので(自分ならそう)、通常はいれていない筈です。頼めばいれること自体は簡単なので、頼んでみるのはアリですが、新しいブラウザがでたときに即更新される訳ではなかったり、世の中全てのブラウザ情報がはいっているワケではないので、余り頼り切るものではないです。自前サーバー使っている人、php.ini を書き換えられる権限を使える環境のヒト以外は、無理して使うほどのものではありません。

ただ、サーバーで使える、使えないに関わらず、browscap.ini はよーするに、「ユーザーエージェント情報のデータベース」なので、制作者はたまにダウンロードしてみるというのは結構有意義かもしれません。また、get_browser() と同様の自前関数を作るのは簡単だったり。そうだ。そうしよう(笑)

browscap.ini は「ブラウザキャパビリティファイル」というらしいです。

スタイルシート自体をサーバーサイド処理送出する

こういうことはふつうあんまりやらないと思いますが、自分の場合必要にかられて使っている方法。これまでのユーザーエージェント判別を理解した上でお読みください。

普通にスタイルシート作って、xxxx.css として HTML からリンクします。このxxxx.css 自体が例えば PHP であればブラウザ判別は勿論内部で行えますのでそれによって送出内容が書き変わるということが可能なわけです。これ読んで「あぁ!そういうやりかたがアッタカー」という方は多いんじゃないでしょうか?環境さえ許せば一番スマートな手法じゃないかと思います。

xxxx.css を xxxx.php としてしまえば済んでしまうハナシですが、そのまま中身の必要な箇所だけ PHP 処理してもブラウザが CSS と判断できない場合があるようです。これは、通常、PHP はサーバー側から mime-type が text/html として送出されるから(PHP 自体の設定によるわけですね)なので、header("Content-type: text/css"); を(最初に)付加します。このへんは PHP の基本でしょうから特に詳しく書きませんが。

ついでといってはなんですが、拡張子 css のままで PHP ファイルとすることも可能ですから、そうしたほうがスマートでしょう。

.htaccess に以下を記述。

<FilesMatch "^xxxx.css$">
ForceType application/x-httpd-php
</FilesMatch>

これで xxxx.css 内に PHP 処理記述が可能になります。.css の全てを PHP とする

AddType application/x-httpd-php .css

としてもいいのですが、.css ファイル全てを PHP として処理してしまうためサーバー負荷が増加するので避けます。レンタルサーバーによっては禁止しているかもしれません。

上記が動作可能な環境においては、あとは制作者が PHP について理解していて、スタイルシートの必要な箇所をブラウザ判別して書き換えてしまうことがいくらでも可能です。ファイル上部でユーザーエージェント取得して、判別して変数ひとつ作ってしまえばいいだけ。if でも switch() でも使って、要素でもクラスでも ID でも必要な箇所が書き変わるようにしちゃう、と。

ここまで覚えちゃえばあとは存分に「ユーザーエージェント毎に異なるスタイルシート設定をする」ことができると思いますが。そうそう必要ないのになんでもかんでもサーバーサイド処理しちゃうと、環境が異なる場合に面倒な手法に戻らざるを得ない場合がでてきますので、その必要性の判断を間違えないようにしましょう。一番重要なのはそういう点です。当然ですが、サーバーサイド処理はサーバー側に負担をかけることになるので、レンタル共用サーバー等であれば使わないにこしたことはないでしょう。

自分の場合は「動的情報(投稿するとか、他サイトの XML だとか)を取り出し、レイアウトを変更する(マップに投稿場所のアイコンだすとか、投稿件数によってブロックのサイズを変更するとか)」というようなモノばっかりここんとこ作っていて、当初は JavaScript DOM でやりくりしてましたが、JavaScript 非動作環境対処等を考慮するとサーバーサイド処理を使えるならソッチでやったほうがなにかと便利なため、こーゆーことを必要にかられて覚えてしまったという経緯があります。

※上記をよく理解できた方は例えば「.js ファイルをサーバーサイド処理する」なんてこともデキルことに気づく筈。これら「サーバーサイド、クライアントのハイブリット処理」とでもいうようなコトを「ウェブデザインとして」やっちゃうのが自分のウリなのですが、環境が許しているなら誰でもできることであって、問題は手法でなくてその結果。

JavaScript でユーザーエージェントを取得し、それに応じたリンク要素を書き出す。

JavaScript の場合、XHTML を見越して外部ファイルにするべきです。内部の記述のリンク先は当然ながら、スクリプトファイルではなくて、HTML からになります。

ユーザーエージェント取得は SSI等とひとまず一緒ですが、JavaScript だとappVersion、appName 等のプロパティも拾えるので、ひととおりどういう値を返すか確認して、処理しやすいものを使います。userAgent だけだと、ダメな理由もあったりしたんだけど、忘れた。

var Mac		= navigator.appVersion.indexOf('Mac',0) != -1;
var Win		= navigator.appVersion.indexOf('Win',0) != -1;
var IE		= navigator.appName.indexOf("Microsoft",0) != -1;
var NN		= navigator.appName.indexOf("Netscape",0) != -1;
var Moz		= navigator.userAgent.indexOf("Gecko") != -1;
var Safari	= navigator.userAgent.indexOf("Safari") != -1;
var iCab	= navigator.appName.indexOf("iCab") != -1;
var Opera	= window.opera?true:false;
var version	= parseInt(navigator.appVersion.charAt(0));
var mversion	= 0;
if (IE) { version += 1;}
if ((navigator.appVersion.indexOf('MSIE 6.',0) != -1) && Win) { version = 6;}
if ((navigator.appVersion.indexOf('MSIE 5.5',0) != -1) && Win) { mversion = 5;}
if ((navigator.appVersion.indexOf('MSIE 4.',0) != -1) && Mac) { version = 4;}
var MacIE = (Mac && IE)?true:false;

新しいブラウザが出たりすると、どんどん増えます。IE のバージョンに関しては、わざわざややこしいことしてますが、そろそろ整理しようかな? appVersion は使えないかも。

ほんで、スタイルシートリンク。

if (IE) {
 if (MacIE) {
  document.write('<link rel="stylesheet" type="text/css" href="./mie.css">');
 } else if (Win) {
  if (version >= 6) {
   document.write('<link rel="stylesheet" type="text/css" href="./wie6.css" charset="Shift_JIS">');
  } else if (version >= 5) {
   if (mversion == 5) {
    document.write('<link rel="stylesheet" type="text/css" href="./wie55.css" charset="Shift_JIS">');
   } else {
    document.write('<link rel="stylesheet" type="text/css" href="./wie5.css" charset="Shift_JIS">');
   }
  }
 }
}

キレイに function 化したい気がしてきた。あと今後は DOM 使うことが考えられます。alternate スタイルシートきりかえはもともと最近のブラウザしか対応していないので、そーしてます。

JavaScriptでユーザーエージェントを取得し、それに応じたスタイルシート記述を返す

直接 CSS コードをdocument.writeする方法。フォントサイズ揃えでたまにやってるのを見ます。JS ソース内に長い CSS 記述をするのは記述ミスしやすいのでやりません。<キッパリ


ちょっとだけ気をつけること

単純にブラウザ判別では困りませんが、サーバーサイド取得のユーザーエージェントの値と、JavaScript の値は異なる場合もあります。サーバーサイドで取得して、JavaScript に渡す、ということもあります。(JavaScript で取得した値をサーバーサイドスクリプトに渡す、というのは結構ややこしかったり)「JavaScript じゃ不可能」なことといえば、筆頭は携帯端末判定。JavaScript に未対応のページとすればいいですが、JavaScript 未対応のPCブラウザと一緒では困りませんか?スタイルシートが携帯でも使えるようになると、ますます判別必要。media 判定との兼ね合いでなんとかできるべきなのでしょうが、現状では確実性がありません。

ブラウザ判別はそもそも自分の無精な性格から必要になったものです。「ひとつのリソースをいかに各種ユーザーエージェントで使いまわすか?」ということ。ユーザーエージェント別に別ページを作るなんてしてられっか。

これがドコまでできるかどうかは一般の方(クライアント)は知らないので、例えば携帯版制作は別途発注されたりするのが現状で、たまに内容自体がたいした量でない場合なにもせずとも携帯でみれたりしますが、「携帯でも見れますよ」というと驚かれる。今迄は確かにPC上でも携帯ブラウザでも独自仕様で突き進んでいる箇所の処理が面倒なのでかなり大変でした。標準準拠や XML 対応ということが進むと「もとのドキュメントはひとつ」というのがごく普通になる筈。

これからどんどん進む携帯コンテンツの制作に関しては、自分も情報収集中なのでそのうち別途まとめてみたいと思います。


ブラウザ判別はナニを判別する必要があるか?

どこまで昔のブラウザを考慮するか、という判断にもよるのですが、だいたい charset をサーバー側で指定して、Shift_JIS にした時点で見れなくなるブラウザもあったりするので、世にあるブラウザ全部のこと考えることはおそらく無理。だいたい HTML の仕様自体、以前は「日本語環境に未対応」だった訳なので、だからといって、全部英語にする、ということにはならないし。「Shift_JIS 以外の方が良い」とか、ムカシはそれなりに対策を検討しましたが、ムカシにこだわるよりコレカラを考えた方がいいような。UTF-8 にした時点で、対応ブラウザはがっつり減ったりするわけだし、IE3 対策講じているより他のこと(先のこと)配慮するほうが重要。ユニバーサリティ、グローバリティ、アクセシビリティ、ユーザビリティという点を考慮することは、やることが増えるというより、やることを絞り込んで、優先順位をつけるということになるので、実は制作手順がシンプルになったりする、と考えられなくもないと思うのです。あれ、関係ないか?

ちなみに「判別して対策が必要なブラウザの判断」は、「見栄えのために行なう」ことバッカリでしょうが、そもそも「HTML でどんな環境でも同じ見栄えになんてナラナイ」と考えれば、例えば「ブラウザメーカーがサポートしてないブラウザは考慮からはずす」とか、「正式バージョン以外は最初から考慮しない」とか、そういう判断もできます。ブラウザ独自拡張を使わない、バグを逆にうまく使った処理等をしない、つまりは仕様準拠した記述を心掛けることが基本ちゅうことで。

意図した結果にならないブラウザの対策を講じるのに、様々なワザを使っていると、仕様の本来の意味合いからはみ出しているかも、という状況になるようなこともありますが、それくらい勘弁してくれ。制作者やユーザーが望んでることは仕様書に全部含まれているとは限らないのだ。仕様書すら知らずに勝手な解釈、自分の環境以外の状況を全く知らない、というのはどうかと思うだけ。

ブラウザデフォルトスタイル

通常、ブラウザアプリケーション自体に仕込まれているものですが、最近のブラウザは「スタイルシート機能の処理」がはいっているだけで、実際にデフォルトスタイルシートを別ファイルで持っていて常にリンクさせているやつがあるみたいです。Safari なんかはそうで、 CSS そのまんまのファイルを見つけた。System → WebKit.framework 内を探して下さい。

このブラウザデフォルトシート自体を書き換えるなんてことはやんないほうがよくて、ユーザースタイルシートを作って適用します。世の中にはまともな HTML が少ないから、細かいところには殆どキキメないですがimg { display:none; }とかやるようなことが考えられなくはない。なんかもっとユーザースタイルシートについても考えてみたい。table td img { display:inline; }なんてすると、テーブルをレイアウトに使って画像だらけで作ってるサイトが分かったり。これ、自分の作ったサイトはほぼ影響ないけど、なんにも見えなくなるのが多い。どうも制作者へのイジメみたいなものしか考え付かん。

更新 2007-02-12 20:41 初回投稿 2005年01月02日 20:48


note contents


筆者プロフィール

フリーのウェブサイトディレクター。音響オペレーター。北海道札幌にて活動中。


Page Top

Web Site designed by Studio Susto