JavaScriptでユーザーが利用しているWebブラウザを判別して処理を変える
Webサイトを構築していく中でユーザーが利用しているWebブラウザによって処理を変えたいことがあります。
そうした場合にはJavaScriptで条件分岐をさせて処理を変える方法をとっていきます。
例えば、JavaScriptのプログラムがWebブラウザで挙動が違ったりうまく動かないといった時に、JSファイルをブラウザによって切り替えるといった対応をすることができます。
ここではJavaScriptでユーザーが利用しているWebブラウザを判別して処理を変える方法をご紹介します。
ユーザーの取得には、userAgentプロパティやuserAgentDataプロパティと、2種類のプロパティを利用していきます。
userAgentは廃止予定ですので、今後はuserAgentDataを利用していくことになってきますが、まだuserAgentDataが有効でないブラウザもありますので、両方の方法でご紹介していきます。
ブラウザ情報を取得する
JavaScriptでユーザーが利用しているWebブラウザの情報を取得するには「window.navigator.userAgent」を使います。navigatorオブジェクトのuserAgentプロパティでユーザーがアクセスした時のユーザー情報が取得できますので、そのユーザーの情報からブラウザの情報を確認します。
const ua = window.navigator.userAgent;
console.log(ua);
処理の結果はconsole.log()でWebブラウザのコンソールに結果を表示させています。
実際にGoogle Chromeでデベロッパーツールを起動してコンソールを確認すると以下のようにGoogle Chromeでアクセスした結果が確認できます。
各Webブラウザの結果では以下のように情報が取得できます。
Google Chrome
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
FireFox
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0
Microsoft Edge
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763
Chromium版 Microsoft Edge
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36 Edg/79.0.309.65
Microsoft Internet Explorer
Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; rv:11.0) like Gecko
Safari
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.2 Safari/605.1.15
Opera
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 OPR/57.0.3098.106
この情報を元にWebブラウザの判別を行って処理を変えます。
しかし、各ブラウザの出力結果を見ていただくとわかると思いますが、Google ChromeでSafariの文字列が入っていたり、Microsoft EdgeやOperaでChromeとSafariの文字列が入っていたりします。
また、2020年1月からリリースされたChromium版のMicrosoft Edgeでも、「Edge」と「Edg」と違いがありますので、新旧ブラウザの判別には気をつけてください。macOS版のMicrosoft EdgeもWindowsと同じです。
これから出力結果の文字列を元にブラウザ判別を行いますが、複数のブラウザの文字列が含まれてくることも計算した上で条件分岐を行っていきます。
ブラウザを判別して処理を変える
ブラウザを判別をユーザーエージェントの情報を元に行っていきますが、ブラウザの情報の文字列で判断していきます。そして文字列を判断するためにindexOf()メソッドを使います。
indexOfメソッドは文字列内に指定した文字列が含まれているか検索するメソッドになります。
引数に検索する文字列を記述してマッチする文字列を探します。見つからなければ-1を返します。
userAgentの情報を入れた変数からindexOfメソッドで文字列を検索し、-1でなければ指定した検索文字列が見つかったので、その文字列を含んでいる場合の処理として条件分岐させます。
const ua = window.navigator.userAgent.toLowerCase();
if (ua.indexOf('msie') !== -1 || ua.indexOf('trident') !== -1) {
console.log('Microsoft Internet Explorer');
} else if (ua.indexOf('edge') !== -1 || ua.indexOf('edg') !== -1) {
console.log('Microsoft Edge');
} else if (ua.indexOf('chrome') !== -1) {
console.log('Google Chrome');
} else if (ua.indexOf('safari') !== -1) {
console.log('Safari');
} else if (ua.indexOf('firefox') !== -1) {
console.log('FireFox');
} else {
console.log('Unknown');
}
toLowerCase()メソッドは、すべて小文字として情報を取得しています。もしuserAgentをtoLowerCaseメソッド無しで情報を取得した場合、文字列の大文字と小文字は区別されますので気をつける必要があります。
Internet ExplorerやEdgeブラウザは古いバージョンを利用していると違いがありますので、OR条件で複数の指定しておきます。
あとは記述する順番を気をつけてもらえば各ブラウザの判断を間違えることはないでしょう。
1つ、サンプルとしてWebブラウザによって読み込むJSファイルを変えるといったサンプルコードを用意しました。
例えばInternet ExplorerやEdgeといったMicrosoft製のブラウザだけうまくJavaScriptが動かないなんてことがあったとして、IEとEdgeだけは別のJSファイルを読み込んで、その他のブラウザは従来のJSファイルを読み込ませるといった条件分岐になります。
<script>
const ua = window.navigator.userAgent;
if(ua.indexOf('Edge') != -1 || ua.indexOf('Edg') != -1 || ua.indexOf('Trident') != -1 || ua.indexOf('MSIE') != -1) {
document.write('<script src="js/script-ms.js"><\/script>');
} else {
document.write('<script src="js/script.js"><\/script>');
}
</script>
条件によってdocument.writeでHTMLでタグを出力しています。
タグを出力する際にはシングルクォーテーションとダブルクォーテーションの入れ子とscriptの終了タグのスラッシュ「/」をバックスラッシュ「\」でエスケープ処理をするのに気をつけてください。
JavaScriptを読み込ませるheadタグまたはbodyの終了タグの直前などに記述してもらえれば良いかと。
もちろんCSSの読み込みの制御にも利用できるでしょう。CSSの場合はCSSハックで制御する方もいるかと思いますが。
Internet Explorerのバーションで処理を変えたい場合では、「MSIE 10」や「MSIE 9」といった文字列検索で対応することができます。その場合は変数を「let」や「const」ではなく「var」で宣言してください。古いバージョンのブラウザはletやconstには対応していないので。
IE 10
Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E)
IE 9
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E)
User Agent Client Hintsによる情報の取得
セキュリティや個人情報の保護の観点からuserAgentは廃止となる流れで、今後はUser Agent Client Hints(UA-CH)で判別していくことになっていくことになるでしょう。
User-Agent Client Hintsが有効なブラウザの場合、JavaScriptでは「navigator.userAgentData()」で情報を取得することができます。
navigator.userAgentData()は、User-Agent Client Hints APIにアクセスしてNavigatorUADataオブジェクトを返します。
console.log()で値を確認しながら見ていきます。
const uaData = navigator.userAgentData;
console.log(uaData);
以下、実行結果になります。
brandsやmobile、platformの情報が並列で返ってくるのが確認できます。
brands: ブラウザーの種類・バージョン情報
mobile: モバイル端末かどうかの情報
platform: OSの情報
また「.userAgentData.brands」とすることで、brandsの情報だけを取得することもできます。
const uaData = navigator.userAgentData.brands;
console.log(uaData);
さらに細かく情報を取得したい場合は、getHighEntropyValues()メソッドで情報を取得していくこともできます。
以下のような引数を指定して、CPUアーキテクチャ情報やデバイスモデル情報などの細かな情報も取得できます。
"architecture"
"bitness"
"model"
"platformVersion"
"uaFullVersion"
"fullVersionList"
以下、サンプルプログラムになります。
await非同期処理の処理を待ってから実装しますが、awaitはasync関数内のみでの使用となりますので、async関数で実行していきます。
試しに、OSの情報を取得してみます。
const uaData = navigator.userAgentData;
(async () => {
const highEntropyValues = await uaData.getHighEntropyValues([
"platform",
"platformVersion",
"architecture",
"model",
"uaFullVersion",
]);
console.log("情報", highEntropyValues);
// OSの情報
const platform = highEntropyValues.platform;
console.log(platform);
// OSのバージョン情報
const platformVersion = highEntropyValues.platformVersion;
console.log(platformVersion);
})();
highEntropyValuesから「platform」の値を指定すればOSの情報が取得できますし、「platformVersion」の値を指定すればOSのバージョン情報が取得できます。
User Agent Client Hintsでブラウザを判別
それでは、User Agent Client Hintsでブラウザを判別してみましょう。
User-Agent Client Hintsがまだ有効でないブラウザもあります。
すべての環境に適応できるように有効のブラウザと無効のブラウザで処理を切り分けるといいでしょう。
if文の条件を「window.navigator.userAgentData」として判別していきます。
if (window.navigator.userAgentData) {
// userAgentDataで判別する(userAgentDataが有効)
} else {
// userAgentで判別する(userAgentDataが無効)
}
無効の場合は従来のuserAgentで処理をします。
以下、サンプルコードになります。
if (window.navigator.userAgentData) {
const uaData = navigator.userAgentData;
console.log(uaData);
// 利用ブラウザーの情報
const brand = uaData.brands[2].brand;
if (brand.indexOf('Edge') !== -1) {
console.log('Microsoft Edge');
} else if (brand.indexOf('Chrome') !== -1) {
console.log('Google Chrome');
} else if (brand.indexOf('Safari') !== -1) {
console.log('Safari');
} else if (brand.indexOf('Firefox') !== -1) {
console.log('FireFox');
} else {
console.log('Unknown');
}
} else {
const ua = window.navigator.userAgent.toLowerCase();
console.log(ua);
if (ua.indexOf('msie') !== -1 || ua.indexOf('trident') !== -1) {
console.log('Internet Explorer');
} else if (ua.indexOf('edge') !== -1 || ua.indexOf('edg') !== -1) {
console.log('Microsoft Edge');
} else if (ua.indexOf('chrome') !== -1) {
console.log('Google Chrome');
} else if (ua.indexOf('safari') !== -1) {
console.log('Safari');
} else if (ua.indexOf('firefox') !== -1) {
console.log('FireFox');
} else {
console.log('Unknown');
}
}
「uaData.brands[2].brand」は、brandの多次元配列からbrand情報を取り出しています。
「[2]」のキー「brand」を指定してブラウザ情報が取得できます。
ブラウザの情報が取得できましたら、あとはindexOf()などでブラウザごとに処理を切り分けることができます。
以下、console.log()の実行結果です。
ただ、User Agent Client HintsのAPIやWebブラウザのアップデートによる仕様変更には注意が必要です。
仕様変更によって配列オブジェクトの構造が変わることもあります。
Google Chrome 122とGoogle Chrome 123では、配列に格納されているインデックス番号が変わっています。
そうなると、ご紹介したサンプルコードでは「uaData.brands[0].brand」でブラウザの情報を取得することになるので、「uaData.brands[2].brand」とbrandsのインデックス番号が2のままだと別の情報となります。(ブラウザエンジン:Chromium – Chrome,Edge,Brave,Arcなど)
配列のインデックス番号をピンポイントで指定するのでなく、配列から対象の文字列を検索すれば、仕様変更で構造が変わっても問題なく対応して処理することができます。
配列から文字列を検索する方法としてsome()メソッドが使えます。
以下、サンプルコードになります。
JavaScript
if (window.navigator.userAgentData) {
const uaData = navigator.userAgentData;
console.log(uaData);
// 利用ブラウザーの情報
const brand = uaData.brands;
console.log(brand);
if (brand.some((el) => { return el.brand === 'Edge' }) === true) {
console.log('Microsoft Edge');
} else if (brand.some((el) => { return el.brand === 'Google Chrome' }) === true) {
console.log('Google Chrome');
} else if (brand.some((el) => { return el.brand === 'Safari' }) === true) {
console.log('Safari');
} else if (brand.some((el) => { return el.brand === 'Firefox' }) === true) {
console.log('Firefox');
} else {
console.log('Unknown');
}
} else {
const ua = window.navigator.userAgent.toLowerCase();
console.log(ua);
if (ua.indexOf('msie') !== -1 || ua.indexOf('trident') !== -1) {
console.log('Internet Explorer');
} else if (ua.indexOf('edge') !== -1 || ua.indexOf('edg') !== -1) {
console.log('Microsoft Edge');
} else if (ua.indexOf('chrome') !== -1) {
console.log('Google Chrome');
} else if (ua.indexOf('safari') !== -1) {
console.log('Safari');
} else if (ua.indexOf('firefox') !== -1) {
console.log('FireFox');
} else {
console.log('Unknown');
}
}
brandsの配列オブジェクトを変数に格納しておき、some()メソッドを使って指定された関数の処理で、brandsの配列の中に対象の要素があるかどうかを判定します。要素がある場合はtrue、ない場合はfalseを返します。
これが完成版かな。
someメソッドを使った文字列の検索については、以下の記事でもご紹介しています。
まとめ
userAgentの廃止が進み、今後はUser Agent Client Hintsを利用していくことになりますので、ユーザー情報で処理の切り分けが必要な部分は早めに対応しておくと良いでしょう。
サポートが終了しているInternet Explorerや同じくらいシェア率の低いOperaは、もう無視してもいいかもしれませんね。
また、WordPressなどPHPが利用できる環境でしたらサーバサイドでの処理のほうがJavaScriptが無効に設定されているユーザーにも対応できますので、PHPでのブラウザ判別をされると良いでしょう。
PHPスクリプトでのWebブラウザ判別方法については、以下の記事で紹介していきます。
User Agent Client HintsのuserAgentDataオブジェクトではmobileやplatformの情報も取得できますので、PCかモバイル端末か、またmacOSやWindows、iPhone、Androidなど、デバイスを判別して処理を切り分けることもできます。
デバイスを判別方法については、以下の記事でご紹介しています。
ぜひ参考にしてください。