JavaScriptでブラウザ判別用のclassをhtmlタグに追加する

いつの時代も手こずらせる

昔ほどではないですが、現在も制作者を困らせるブラウザ問題。
「IE6対応すか?大丈夫っすよ!」と、ついうっかり安請け合いして泣きを見た人もいることでしょう。 1ピクセル合わせるのに一晩中サイトを徘徊した挙句、「結局できませんでしたー」なんてことも・・。
同じように表示するだけなのにどうしてこんなに大変なものか・・!

以前はCSSのみで無理やりなんとかするCSSハックが流行りましたが、現在はJavaScriptが気軽に使える時代ですのでどんどん使って、正しくすっきりした健全なCSSを書いて、少しでも気持ちを軽くさせましょう。

頭にブラウザごとのclassを書くだけ

私のやり方ですが、後述するJavaScriptを読み込むことで、こんな感じでCSSが書けるようになります。

/* デフォルトのCSS */
p.message {
    background-color: blue;
}
/* IEのみに適用 */
.ie p.message {
    background-color: green;
}
/* IEバージョン11のみに適用 */
.ie11 p.message {
    background-color: gray;
}
/* IEバージョン5.5のみに適用 */
.ie5_5 p.message {
    background-color: black;
}
/* safari5.1.xとfirefoxのみに適用 */
.safari5_1 p.message ,
.firefox p.message {
    background-color: red;
}

CSSハックよりは健康によさそうな書き方でしょ?

ブラウザ判別用JavaScript

まず、JavaScriptは本体は以下になります。コピペしてファイル名add_browser_class.jsとかにして適当に保存してください。

// -------------------------------------------------------------------
// htmlタグに以下のブラウザ判別用クラスを追加します
// -------------------------------------------------------------------
/*
    htmlタグに以下のブラウザ判別用クラスを追加します。
    例えばIE6なら <html class="ie ie6"> となります。
    対象:ie, chrome, firefox, oepra, sagari
    ※一応将来のバージョンにも対応してるのでIE99でも「class="ie ie99"」となります。
    ※ブラウザ名は全て小文字指定、バージョン指定の部分は、最初のマイナーバージョンまで、小数点の0のみはピリオドごと消える、「.」は「_」になる。
    例:「Safari」→「safari」
    例:「IE11.0」→「ie11」
    例:「IE5.5」→「ie5_5」
    例:「Safari5.1.7」→「safari5_1」
*/
function addBrowserClass() {
    var __add = function(name, ver){
        if(document.documentElement.className){ document.documentElement.className += ' '; }
        document.documentElement.className += name + (ver!='' ? ' ' + name+(ver*1).toString().replace('.','_') : '');
    }
    var userAgent = window.navigator.userAgent.toLowerCase();
    var appVersion = window.navigator.appVersion.toLowerCase();
    if( get = userAgent.match( /msie (\d+(\.\d+)?)/i ) )              { __add('ie',      get[1]); }
    else if( get = userAgent.match( /Trident.+rv\:(\d+(\.\d+)?)/i ) ) { __add('ie',      get[1]); }
    else if( get = userAgent.match( /chrome\/(\d+(\.\d+)?)/i ) )      { __add('chrome',  get[1]); }
    else if( get = userAgent.match( /firefox\/(\d+(\.\d+)?)/i ) )     { __add('firefox', get[1]); }
    else if( get = userAgent.match( /opera\/(\d+(\.\d+)?)/i ) )       { __add('opera',   get[1]); }
    else if( get = userAgent.match( /safari\/(\d+(\.\d+)?)/i ) )      { __add('safari',  get[1]); }

    // ついでにモバイルOS情報を付加する→ios(iphone, ipad, ipod), android
    if( get = userAgent.match( /iPhone OS (\d+(\.\d+)?)/i ) )    { __add('ios',     get[1]); }
    if( get = userAgent.match( /iPhone;/i ) )                    { __add('iphone',  ''); }
    else if( get = userAgent.match( /iPod;/i ) )                 { __add('ipod',    ''); }
    else if( get = userAgent.match( /iPad;/i ) )                 { __add('ipad',    ''); }
    else if( get = userAgent.match( /Android (\d+(\.\d+)?)/i ) ) { __add('android', get[1]); }
}

次に、このスクリプトをHTML側で読み込んで関数を実行するだけです。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="add_browser_class.js"></script>
<script>
<!--
addBrowserClass();
//-->
</script>
<link rel="stylesheet" href="./style.css" type="text/css">
</head>
<body>
<p class="message">テストメッセージです。</p>
</body>
</html>

上記addBrowserClass()が呼び出されることによって、実行時に<html>タグにブラウザ判別用文字列のclassがセットされる仕組みです。

これで冒頭で紹介したようなCSSの書き方が出来るようになります。 jQueryとか外部のスクリプトを一切使ってないので、IE5.5とかでも普通に動きます。

あとはCSSをガリガリお好きに弄っちゃって下さい!
素敵なCSSライフを!

参考にさせていただいたサイト

2014.5.22追記

以前のコードにバグがあり、iOS版Chromeでエラーが発生していたので修正しました。 また、ついでにモバイルOS判別用のコードも追加しました。