ブラウザを判定する(ブラウザスニッフィング)
はじめに
ブラウザをユーザーエージェントの使用なしに、ブラウザの固有動作を元に判定します。
これは、ユーザーエージェント偽装などへの対策として優秀です。また、今後のブラウザの増加などで意図せずユーザーエージェント文字列の衝突による誤判定を防ぐこともできます。(ただし、動作の変更により問題が発生する可能性があります)
ブラウザを判定する
ua.jsvar ua = (function() {
return {
IE: /*@cc_on!@*/false || !!document.documentMode, // IE 4-11
// Trident:!!document.uniqueID, // IE (MSHTML), Edge Legacy (EdgeHTML)
Gecko: 'MozAppearance' in document.documentElement.style,
// Firefox *
WebKit: /constructor/i.test(window.HTMLElement) || (!window.chrome && !!window.webkitAudioContext),
// Safari, iOS Third Party Browser, Chrome 27-
Blink: !!window.chrome, // Chrome 1+, Edge 79+, Opera 14+
// Presto: !!window.opera, // Opera 12-
Mobile: 'orientation' in window,
Touch: 'ontouchstart' in window
};
})();
実行例
IE を判定する
// IE 4-10
var isIE = /*@cc_on!@*/false;
// IE 8-11 (EmulateIE 5, 7-11)
var isIE = !!document.documentMode;
// IE 4-11
var isIE = /*@cc_on!@*/false || !!document.documentMode;
@cc_on
@cc_on ~ @
は、条件付きコンパイル機能を有効にする記述です。
条件付きコンパイルは、 JScript の機能でバージョン毎に互換性を維持しながら JScript の新機能を使用するための機能です。 IE 4 (JScript 3.0) で登場して、 IE 11 で廃止された。当然ながら、 IE 以外では実装されていません。
/*@cc_on!@*/
は、!
(否定)の処理を実行するという意味です。 そのため、/*@cc_on!@*/false
は!false
となり。対応ブラウザではtrue
として処理されます。非対応ブラウザでは、/*@cc_on!@*/
はコメント扱いであるため、false
として処理されます。
※対応時期については、諸説あるようです(IE 10-, IE 4-10)
document.documentMode
document.documentMode
は、 IE 8 で実装されたドキュメントモードの機能です。ドキュメントモードで指定したバージョンの IE でエミュレートしてウェブページを表示します。
IE 5, 7-11 をエミュレートできます。
ドキュメントモードの指定は、<meta http-equiv="X-UA-Compatible">
を使用してください。
※document.documentMode
は、ブラウザのバージョンではありません。
エミュレート中のドキュメントモードのバージョンです。
※ Edge Legacy は、document.documentMode
に非対応です。
<meta http-equiv="X-UA-Compatible">
は、対応しています。
※ Windows 10 以降では、ドキュメントモードは非推奨です。
※ドキュメント モードとエンタープライズ モード | Microsoft Learn
※IE対策の「X-UA-Compatible:IE=edge」は必要か?
document.all
この方法は既に利用できません。 IE 以外のブラウザが document.all
に対応したため、この方法は利用できません。
Trident を判定する
// IE, Edge Legacy
var isTrident = !!document.uniqueID;
// IE 4-11, Edge Legacy
var isTrident = /*@cc_on!@*/false || !!document.uniqueID;
※「Trident」は、 IE, Edge Legacy のレタリングエンジンの名称です。
※ Trident は、ライブラリファイルの名称から MSHTML とも呼ばれています。
※ Edge Legacy は、 Trident からフォークされた EdgeHTML を使用しています。
document.uniqueID の対応時期
正確な対応時期は不明だが、 IE 9 で実装済みであることは次ソースからうかがえる。実際はそれよりもまえに実装されているものと考えられます。
Gecko 判定について
// Firefox *
var isFF = 'MozAppearance' in document.documentElement.style;
// Firefox 1.5+
var isFF = 'InstallTrigger' in window;
var isFF = typeof InstallTrigger !== 'undefined';
※「Gecko」は、Firefox と派生ブラウザのレタリングエンジンの名称です。
※window.InstallTrigger
は、 Firefox の旧拡張機能をウェブページからインストールするための機能です。WebExtension(新拡張機能)には対応していません。現在は、初期設定でnull
初期化されており、使用することはできません。いつなくなってもおかしくない機能です。
1754441 - Deprecate InstallTrigger
window.globalStorage
// Firefox 2-13
var isFF = window.globalStorage;
この方法は既に利用できません。 Firefox 13 で window.globalStorage が削除されました。
WebKit を判定する
// Safari, Chrome 27-
var isSafari = /constructor/i.test(window.HTMLElement) || (!window.chrome && !!window.webkitAudioContext);
// Safari 9-, Chrome 27-
var isSafari = /constructor/i.test(window.HTMLElement);
// Safari 3.1+
var isSafari = !window.chrome && !!window.webkitAudioContext;
※ WebKit は、現在主に Safari / iOS Third Party Browser で使用されています。
'WebkitAppearance' in document.documentElement.style
var isWebKit = !window.chrome && 'WebkitAppearance' in document.documentElement.style;
この方法は既に利用できません。 Firefox 64+ が-webkit-appearance
に対応したことにより WebKit の判定として機能していません。
/constructor/i.test(window.HTMLElement)
// Safari 9-
var isSafari = /constructor/i.test(window.HTMLElement);
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
この方法は、既に利用できません。 Safari10 から機能していません。
Object.prototype.toString.call(window.HTMLElement)
は、[object HTMLElementConstructor]
を期待しています。
'webkitAudioContext' in window
// Safari 3.1+
var isSafari = !window.chrome && !!window.webkitAudioContext;
webkit プレフィックスを使用した単純な判定です。 AudioContext に特別な意味はありません。
そのため、「webkit プレフィックスが廃止される」又は「webkit プレフィックスに別ブラウザが対応した」場合修正が必要になります。
Blink を判定する
// Chrome 1+ (Headless Chrome を除く), Edge 79+ (Edge Chronium), Opera 14+
var isBlink = !!window.chrome;
// Chrome 1-70
var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
Blink は、 WebKit のフォークです。そのため、古いバージョンの Chromium 系のブラウザは、 WebKit として判定されます。
※ Chrome 28 以降 Blink が使用されています。
※ Headless Chrome は、window.chrome
が存在しないため、判定できません。
window.chrome
Chrome 1+ から存在する機能です。window.chrome
は、インラインインストール(chrome.webstore.install()
、Chrome Web Store を経由しなくても Chrome 拡張機能を追加できるインストールボタンをウェブサイトに配置できる機能)などを使用するための Chronium 固有の機能です。ただし、インラインインストールは Chrome 2 から非推奨となり、 Chrome 71 で廃止された。
ただし、 Chrome 1 から存在するため、正確には Blink を判定できていません。 Chrome 1-27 は、 WebKit であるため、正確な Blink 判定はではありません。ですが、困ることもないため、このままとします。
Presto を判定する
// Opera 12-
var isPresto = !!window.opera;
※「Presto」は、Opera 12 までのレタリングエンジンの名称です。
※ Opera は、Opera 14 から Chromium ベースで開発されているため、 Blink で判定します。
window.opera
window.opera
は、 Chronium 対応により削除されました。
window.opera
がいつから存在するのか確認できていません、ですが最低でも Opera 8 の時点では存在していたようです。
備考:スマホ・タブレット・デスクトップを判定する
var isMobile = 'orientation' in window;
var isPhone = Math.min(window.screen.width, window.screen.height) < 512;
var isTablet = isMobile && !isPhone;
var isDesktop = !isMobile && !isPhone;
※画面サイズ(ピクセルサイズ)境界の 512
に根拠はありません。
最近の画面サイズの動向を元に適時変更してください。
備考:機能毎に判定する
特定の機能に対応しているか否かは、ブラウザ単位で判定すべきではありません。機能単位で実装有無を確認して個別に対応すべきです。
if (window.requestAnimationFrame) {
window.requestAnimationFrame(function() {
// ...
});
}
@supports (display: grid) {
div {
display: grid;
}
}
※@supports
は、 Firefox22+, Safari9+, Chrome28+ で利用可能です。
@supports - CSS: カスケーディングスタイルシート | MDN
※ CSS によるブラウザ判定は、本記事の主題ではないため、簡略します。