スマートフォン端末で電話発信するa要素「tel」をPC版で無効にする方法

新機種が出るたびに増えるスマートフォン

a要素にhref="tel:電話番号"を指定すると、電話発信用のリンクを作れます。スマホならタップするだけで通話画面に移れるので、店舗サイトや問い合わせページではまず外せない機能です。

ただ困るのが、レスポンシブで同じマークアップをPCにもそのまま出しているとき。私も昔、電話番号をクリックしたPCユーザーから「押しても何も起きない」「見慣れないアプリが立ち上がった」と言われて、初めて出し分けの必要性に気づきました。環境によっては通話用のアプリが勝手に開こうとして、かえって不親切になってしまうんですよね。

この記事では、PCではtel:リンクをクリックしても反応しないようにしつつ、スマホでは今まで通り発信できる状態を保つやり方をまとめます。

結論:まずはCSSだけで無効化できる

以前はjQueryでユーザーエージェントを見て判別する方法が定番でした。ただ、この記事を書き直すにあたって改めて調べてみると、今はCSSのメディア特性 pointerpointer-events を組み合わせる方が素直で、JavaScriptもjQueryも要りません。

HTML

<a href="tel:0120123456">0120-12-3456</a>

マークアップはごく普通のtel:リンクのままでOKです。HTML側に特別な目印を足す必要はありません。

CSS

/* マウスなど精細なポインタを持つ環境(=おおむねPC)だけ無効化 */
@media (pointer: fine) {
  a[href^="tel:"] {
    pointer-events: none;
    cursor: default;
  }
}

やっていることは2つです。@media (pointer: fine) で「マウスのような精度の高いポインタが主入力の環境」に絞り込み、その中でtel:リンクに pointer-events: none を当てています。

pointer-events: none を指定した要素は、クリックやホバーといったポインタ操作のターゲットにならなくなります。つまりPCでリンクを押しても発信の動作が始まりません。あわせて cursor: default を入れているのは、a要素自体は残っているのでマウスを乗せると指マークになってしまうため。カーソルを通常の矢印に戻して、リンクではないように見せています。

pointer メディア特性の値は、マウスなど精度の高いポインタが fine、指でのタッチ操作のように精度が粗いものが coarse、ポインティングデバイスを持たない環境が none です(MDN: pointer)。pointer-events の詳しい挙動もMDNにまとまっています(MDN: pointer-events)。

知っておきたい注意点

手軽なぶん、いくつかクセもあるので触れておきます。

キーボード操作は止まらない

pointer-events: none はあくまでポインタ操作を無効にするだけで、キーボードのフォーカスやEnterでの実行は残ります。マウスユーザー向けの対策と割り切っておくのが安全です。厳密にクリックそのものを止めたい場合は、後述のJSでイベントをキャンセルする方法と併用するとよいでしょう。

「pointer: fine = PC」ではない

タッチとマウスの両方を持つノートPCや、逆にマウスをつないだタブレットなど、境界のあいまいな端末も増えています。pointer: fine は「PC判定」ではなく「精細なポインタが主入力かどうか」を見ているだけ、という点は頭に置いておきたいところです。とはいえ実務では、これで困るケースはかなり減らせます。

どうしてもJSで制御したいとき

CSSだけでは足りない、クリックを確実に無効化したい、という場合はJavaScript側で処理する手もあります。

// マウス環境ではtel:リンクのクリックをキャンセル
if (window.matchMedia('(pointer: fine)').matches) {
  document.querySelectorAll('a[href^="tel:"]').forEach(function (a) {
    a.addEventListener('click', function (e) {
      e.preventDefault();
    });
  });
}

ポイントは、判定基準をユーザーエージェント文字列ではなく matchMedia のポインタ判定に置き換えていること。navigator.userAgent での端末判定は、文字列が偽装されたり新端末で当たらなかったりと崩れやすく、今はあまり推奨されません。CSSと同じ pointer: fine を基準にしておけば、判定の考え方をそろえられて管理も楽になります。

まとめ

PCでtel:リンクを無効にしたいなら、まずは @media (pointer: fine)pointer-events: none のCSSだけで試すのがおすすめです。HTMLをいじらずに済み、jQueryへの依存もなくなります。クリックを厳密に止めたいときだけ、同じポインタ判定を使ったJavaScriptを足す。この順番で考えると、シンプルさと確実さのバランスが取りやすいはずです。

参考:リンクをスマートフォン端末以外では無効にする – Qiita(従来のjQuery+UA判定によるアプローチ)