なぜ「Chrome 判定」ユーティリティが欲しくなるのか
業務システムを書いていると、
「ほとんどのユーザーは Chrome(または Chrome 系)を使っている」という前提で設計されることが多いです。
その中で、次のようなニーズが出てきます。
Chrome だけがサポートしている機能を使いたい。
Chrome では OK だけど、他ブラウザではフォールバックしたい。
逆に、Chrome 特有のバグに対してだけワークアラウンドを入れたい。
こういうときに、毎回 navigator.userAgent を直接いじるのではなく、
「Chrome 判定ユーティリティ」を一つ決めておくと、コードがかなり整理されます。
基本の考え方:Chrome 判定は userAgent だけだと危険
まず押さえておきたいのは、
「userAgent に Chrome と書いてあるからといって、必ずしも“純粋な Chrome”とは限らない」
ということです。
代表的な例として、次のようなブラウザがあります。
新しい Microsoft Edge(Chromium ベース)は Edg/ を名乗りつつ Chrome/ も含んでいる。
一部のブラウザは、互換性のために Chrome を名乗ることがある。
なので、単純に
navigator.userAgent.includes("Chrome")
JavaScriptだけで判定すると、「Chrome っぽいもの全部」が引っかかってしまいます。
業務で「Chrome だけにしたい」場面では、
「Chrome だが Edge ではない」「Chrome だが他の Chromium 系ではない」
といったフィルタリングが必要になることがあります。
シンプルな Chrome 判定ユーティリティを作る
まずは「Edge を除いた Chrome」を判定する
実務でよく使うレベルの Chrome 判定をユーティリティにしてみます。
function isChrome() {
if (typeof navigator === "undefined") {
return false;
}
const ua = navigator.userAgent;
const isEdge = /Edg\//.test(ua); // 新 Edge
const isOpera = /OPR\//.test(ua); // Opera など
const hasChrome = /Chrome\//.test(ua);
return hasChrome && !isEdge && !isOpera;
}
JavaScriptここでやっていることを噛み砕くとこうです。
Chrome/ という文字列が含まれているかを見る。
ただし、Edg/(新 Edge)や OPR/(Opera)も Chrome/ を含むので、それらは除外する。
結果として、「いわゆる“素の Chrome”」だけを true にする。
使い方はとてもシンプルです。
if (isChrome()) {
console.log("Chrome 向けの処理を実行");
} else {
console.log("それ以外のブラウザ向けの処理を実行");
}
JavaScriptここでの重要ポイントは、
「判定ロジックをアプリ本体にベタ書きせず、必ず isChrome() を経由する」ことです。
将来 Edge や他ブラウザの userAgent 仕様が変わっても、
直すのはこの関数だけで済みます。
Chrome 判定をどう使うか(具体例)
Chrome だけ新しい API を使い、それ以外はフォールバック
例えば、「Chrome では navigator.clipboard を使い、
それ以外では古い document.execCommand("copy") を使う」ようなケース。
async function copyText(text) {
if (isChrome() && navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text);
} else {
fallbackCopy(text);
}
}
JavaScriptここでは、
Chrome であること
かつnavigator.clipboard が使えること
の両方を見ています。
本当は「ブラウザ名」ではなく「機能の有無」で判定するのが理想ですが、
「Chrome だけ先行している機能を試したい」といった場面では、
Chrome 判定を条件に含めることがあります。
Chrome 特有のバグ回避を入れる
例えば、「特定バージョンの Chrome だけでレイアウトが崩れる」というバグに遭遇したとします。
その場合、次のように Chrome だけにワークアラウンドを入れることができます。
function setupLayout() {
if (isChrome()) {
document.body.classList.add("chrome-layout-fix");
}
}
JavaScriptCSS 側で、Chrome 向けの微調整を当てるイメージです。
body.chrome-layout-fix .some-element {
/* Chrome だけの調整 */
}
JavaScriptこうしておけば、
「Chrome のバグが直ったから、この対応を消したい」となったときも、isChrome() を使っている箇所だけを見ればよくなります。
「Chrome 判定」と「機能判定」のバランス
ここで一つ、設計としてとても大事な話をしておきます。
本来、フロントエンドの世界では
「ブラウザ名で分岐するより、機能の有無で分岐するべき」
というのが基本方針です。
例えば、「このブラウザで fetch が使えるか?」を知りたいとき、
本当はこう書くのが正解です。
if (typeof fetch === "function") {
// fetch を使う
} else {
// フォールバック
}
JavaScriptこれを「Chrome だから OK」「それ以外はダメ」とブラウザ名で判定してしまうと、
将来のブラウザやバージョンアップに対応しづらくなります。
なので、Chrome 判定ユーティリティは、
どうしても Chrome だけに限定したい実験的機能
Chrome 特有のバグ回避
のような「名前でしか切れない事情」があるときにだけ使う、
という意識を持っておくと健全です。
小さな練習で感覚をつかむ
今使っているブラウザで、開発者ツールのコンソールを開いて、
次のように打ってみてください。
navigator.userAgent
JavaScriptそこに Chrome/ や Edg/、OPR/ がどう入っているかを実際に目で見ると、
「さっきの正規表現が何をしているのか」が一気に腑に落ちます。
そのうえで、自分のプロジェクトに
export function isChrome() { ... }
JavaScriptを一つ置いて、
「Chrome かどうかを知りたくなったら、必ずこれを呼ぶ」
というルールにしてみてください。
それができた瞬間、あなたのコードは
「場当たり的な Chrome 対応」から
「設計された Chrome 対応」に変わります。
