JavaScript Tips | 基本・共通ユーティリティ:環境 – Chrome 判定

JavaScript JavaScript
スポンサーリンク

なぜ「Chrome 判定」ユーティリティが欲しくなるのか

業務システムを書いていると、
「ほとんどのユーザーは Chrome(または Chrome 系)を使っている」という前提で設計されることが多いです。

その中で、次のようなニーズが出てきます。

Chrome だけがサポートしている機能を使いたい。
Chrome では OK だけど、他ブラウザではフォールバックしたい。
逆に、Chrome 特有のバグに対してだけワークアラウンドを入れたい。

こういうときに、毎回 navigator.userAgent を直接いじるのではなく、
「Chrome 判定ユーティリティ」を一つ決めておくと、コードがかなり整理されます。


基本の考え方:Chrome 判定は userAgent だけだと危険

まず押さえておきたいのは、
userAgentChrome と書いてあるからといって、必ずしも“純粋な 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");
  }
}
JavaScript

CSS 側で、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 対応」に変わります。

タイトルとURLをコピーしました