ブラウザを判定する(ブラウザスニッフィング)
はじめに
ブラウザをユーザーエージェントの使用なしに、ブラウザの固有動作を元に判定します。
これは、ユーザーエージェント偽装などへの対策として優秀です。また、今後のブラウザの増加などで意図せずユーザーエージェント文字列の衝突による誤判定を防ぐこともできます。(ただし、動作の変更により問題が発生する可能性があります)
ブラウザを判定する
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 によるブラウザ判定は、本記事の主題ではないため、簡略します。