ブラウザを判定する(ブラウザスニッフィング)

はじめに

ブラウザをユーザーエージェントの使用なしに、ブラウザの固有動作を元に判定します。

これは、ユーザーエージェント偽装などへの対策として優秀です。また、今後のブラウザの増加などで意図せずユーザーエージェント文字列の衝突による誤判定を防ぐこともできます。(ただし、動作の変更により問題が発生する可能性があります)

ブラウザを判定する

ua.jsvar ua = (function() {
  return {
    IE:     /*@cc_on!@*/false || !!document.documentMode, // IE4-11
//  Trident:!!document.uniqueID,                          // IE, Edge Legacy (EdgeHTML)
    Gecko:  'MozAppearance' in document.documentElement.style,
                                                          // Firefox*
    WebKit: Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || (!window.chrome && 'webkitAudioContext' in window),
                                                          // Safari, iOS Third Party Browser, Chrome27-
    Blink:  !!window.chrome,                              // Chromium (Chrome28+, Edge, ...)
//  Presto: !!window.opera,                               // Opera12-
    Mobile: 'orientation' in window,
    Touch:  'ontouchstart' in document
  };
})();

機能毎に判定する

特定の機能に対応しているか否かは、ブラウザ単位で判定すべきではありません。機能単位で実装有無を確認して個別に対応すべきです。

if (window.requestAnimationFrame) {
  window.requestAnimationFrame(function() {
    // ...
  });
}

if (window.requestIdleCallback) {
  window.requestIdleCallback(function() {
    // ...
  });
}
@supports (display: grid) {
  div {
    display: grid;
  }
}

@supportsは、 Firefox22+, Safari9+, Chrome28+ で利用可能です。
 @supports - CSS: カスケーディングスタイルシート | MDN
※ CSS によるブラウザ判定は、本記事の主題ではないため、簡略します。

IE を判定する

// IE4-10
/*@cc_on!@*/false

// IE8-11 (EmulateIE5,7-11)
!!document.documentMode

// IE4-11
/*@cc_on!@*/false || !!document.documentMode
@cc_on

@cc_on ~ @は、条件付きコンパイル機能を有効にする記述です。

条件付きコンパイルは、 JScript の機能でバージョン毎に互換性を維持しながら JScript の新機能を使用するための機能です。 IE4 (JScript 3.0) で登場して、 IE11 で廃止された。当然ながら、 IE 以外では実装されていません。

/*@cc_on!@*/は、!(否定)の処理を実行するという意味です。 そのため、/*@cc_on!@*/false!falseとなり。対応ブラウザではtrueとして処理されます。非対応ブラウザでは、/*@cc_on!@*/はコメント扱いであるため、falseとして処理されます。

※対応時期については、諸説あるようです(IE10-, IE4-10)

document.documentMode

document.documentModeは、 IE8 で実装されたドキュメントモードの機能です。ドキュメントモードで指定したバージョンの IE でエミュレートしてウェブページを表示します。

IE5,7-11 をエミュレートできます。
ドキュメントモードの指定は、<meta http-equiv="X-UA-Compatible">を使用してください。

document.documentModeは、ブラウザのバージョンではありません。
 エミュレート中のドキュメントモードのバージョンです。
※ Edge Legacy は、document.documentModeに非対応です。
 <meta http-equiv="X-UA-Compatible">は、対応しています。
※ Windows10 以降では、ドキュメントモードは非推奨です。
ドキュメント モードとエンタープライズ モード | Microsoft Learn
IE対策の「X-UA-Compatible:IE=edge」は必要か?

Trident を判定する

// IE, Edge Legacy
!!document.uniqueID

// IE4-11, Edge Legacy
/*@cc_on!@*/false || !!document.uniqueID

※「Trident」は、 IE, Edge Legacy のレタリングエンジンの名称です。

document.uniqueID の対応時期

正確な対応時期は不明だが、 IE9 で実装済みであることは次ソースからうかがえる。実際はそれよりもまえに実装されているものと考えられます。

Gecko 判定について

// Firefox *
var isFF = 'MozAppearance' in document.documentElement.style;

// Firefox 1.5+
var isFF = typeof InstallTrigger !== "undefined";

※「Gecko」は、Firefox と派生ブラウザのレタリングエンジンの名称です。
window.InstallTriggerは、 Firefox の旧拡張機能をウェブページからインストールするための機能です。WebExtension(新拡張機能)には対応していません。現在は、初期設定でnull初期化されており、使用することはできません。いつなくなってもおかしくない機能です。
 1754441 - Deprecate InstallTrigger

WebKit を判定する

// Safari9-, Chrome27-
Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0

// Safari3.1+
!window.chrome && 'webkitAudioContext' in window

※ 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)

// Safari9-
var isSafari = /constructor/i.test(window.HTMLElement);
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;

この方法は、既に利用できません。 Safari10 から機能していません。

Blink を判定する

Blink は、 WebKit のフォークです。そのため、古いバージョンの Chromium 系のブラウザは、 WebKit として判定されます。

※ Chrome 28 以降 Blink が使用されています。

Presto を判定する

※「Presto」は、Opera 12 までのレタリングエンジンの名称です。
※ Opera は、Opera 14 から Chromium ベースで開発されているため、 Blink で判定します。

参考