【CSS】スマホではhoverを無効にする方法(PCだけホバーを有効にする)

【CSS】スマホでは:hoverを無効にする方法(PCだけhoverを有効にする) CSS
【CSS】スマホでは:hoverを無効にする方法(PCだけhoverを有効にする)
スポンサーリンク

サイトをコーディングしているとき、ほぼ必ずリンク要素などにホバーアクションを付けるかと思います。

ホバーアクションを付与するには、CSSで:hoverを使いますよね。

:hoverを付けた要素にPCのマウスカーソルを合わせれば、要素の色が変わるなどが起こりますが、スマホではどうなるでしょうか?

例えば、タップしたあとに:hoverのスタイルが残ったり、リンクを押すまでに二回タップが必要になったりすることがあります。これはイケていない…!

そのため、実際の案件では「PCではhoverを有効にし、スマホではhoverを無効にする」という実装を行う必要があります。

でも、難しいことは全くありません!

この記事では、CSSのメディアクエリを使ってスマホのhoverを無効にする方法を解説します。
コピペできるSassの便利コードも掲載しているので、ぜひご覧ください。

本記事の執筆者:マサトラ

フリーランス歴4年のWebエンジニア。現在は20社以上のWeb制作会社社様と提携し、WordPress構築やLP制作を中心に月3~5件のペースでサイト制作を手がけています。
このブログでは、実務で得た知識やノウハウ、制作現場での気づきを、フリーランスとして活動中の方はもちろん、これからWeb制作を仕事にしたいと考えている方にも役立つよう発信しています。

スポンサーリンク

スマホで:hoverが問題になる理由

CSSの:hoverは、本来マウスカーソルを要素の上に乗せたときに適用されるスタイルです。

しかしスマートフォンはマウスではなくタッチ操作のため、:hoverの挙動がPCとは異なります。

PCでは、「カーソルを要素に載せる+クリック」という二段階の動作がありますが、スマホでは「タップ」の一段階のみですよね。

:hoverだと、そのタップ時に、ホバーアクションが発動してしまいます。

例えば、ホバーしたらボタンの色が変わるようにしていた場合、スマホでタップすると「色が中途半端に変わっている最中にリンク遷移してしまう」というようなことが起こります。
ホバーとクリックが同時に起こっているイメージです。

私がまだ駆け出しの頃の実体験ですが、

マサトラ
マサトラ

ディレクターさんの指示どおりボタンにホバーアクションを付けたけど、スマホだとボタンの色が変わっている途中でリンク遷移するな…。
これはなんか微妙な気がするけど…でも何も言われないから、こういうもんなのかな…?

と気になっていました。

結論としては、「PCでは:hoverを有効にし、スマホでは:hoverを適用しない」という実装を行うことが必要です。

その頃に取引させていただいた制作会社様からは特に指摘は無かったのですが、やはり気になると思って自分で調査・学習しました。

この実装をしていないサイトが意外と多いのですが、ディレクターさんからの指示が無くても当然のこととして実装しましょう!

では、具体的に解説していきます。

CSSでスマホのhoverを無効にする方法 (オススメ)

スマホで:hoverによる問題を防ぐには、CSSのメディアクエリを使って「hoverが可能なデバイスだけに:hoverを適用する」という方法がよく使われます。

なぜなら簡単だから!

具体的には、hoverpointerというメディアクエリを組み合わせます。

@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    opacity: 0.7;
  }
}

この指定はどういうことかと言うと、次の条件を満たす場合にのみ:hoverを有効にする、ということです。

  • hover: hover → hover操作が可能なデバイス
  • pointer: fine → マウスのような精度の高いポインター

つまり、PCなどのマウス操作の環境では:hoverが有効になり、スマートフォンのようなタッチ操作のデバイスでは:hoverが適用されない、という条件設定になります。

この方法を使うことで、スマホ特有の「タップ後に:hoverが残る」といった現象を回避できます。

hover / pointer メディアクエリとは

これまで紹介したhoverpointerは、CSS Media Queries Level 4で追加されたメディアクエリです。

従来のメディアクエリはwidthのように画面サイズを基準に判定していましたが、hoverpointerは「入力デバイスの特性」を基準に判定できるようになっています。

そのため、画面幅ではなく「ユーザーがどのように操作しているか」に応じてスタイルを切り替えることができます。

hover

hoverは、そのデバイスがhover操作に対応しているかどうかを判定するメディアクエリです。

例えば、マウス操作のPCではカーソルを要素の上に乗せることができるため、hover: hoverが成立します。一方、スマートフォンのようなタッチ操作のデバイスでは、通常はhover操作ができないためhover: noneになります。

この仕組みを利用すると、「hoverできるデバイスだけに:hoverのスタイルを適用する」といった制御が可能になります。

pointer

pointerは、入力デバイスのポインター精度を判定するメディアクエリです。

主に次の3つの値があります。

  • fine:マウスのように精度の高いポインター
  • coarse:指などの粗いポインター(タッチ操作)
  • none:ポインターが存在しない環境

そのため、hoverpointerを組み合わせることで「マウス操作の環境だけhoverを有効にする」といった制御が可能になります。

width判定(max-width)は正しい方法ではない

スマホで:hoverを無効にする方法として、画面幅で判定する方法を見かけることがあります。

例えば、次のようにmax-widthを使ってスマホサイズのときに:hoverを無効にする方法です。

@media (max-width: 768px) {
  .btn:hover {
    opacity: 1;
  }
}

一見すると問題なさそうに見えますが、この方法は正しい判定とは言えません。

理由は、画面幅と入力デバイスは必ずしも一致しないためです。

例えば、タッチ操作ができる大きめのタブレットではこの条件範囲に収まりませんよね。

そのため、単純にmax-widthでスマホを判定するのではなく、前述のhoverpointerといったメディアクエリを使う方法をオススメします。

スポンサーリンク

IE11にも対応する場合のコード

ただ、hoverpointerといったメディアクエリを使う方法はちょっとした問題があります。

それは、IE11には対応していない、ということです。

正直なところ、IE11への対応を求められるケースは実案件では少なくなってきましたが、対応させることは簡単なので、以下のコードを使用した方が確実です。

@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    opacity: 0.7;
  }
}

//IE11用に以下のコードも追加
@media (-ms-high-contrast: none), (-ms-high-contrast: active) {
  .btn:hover {
    opacity: 0.7;
  }
}

Sassでhover用mixinを作る (コピペ可)

実案件では、:hoverのスタイルを複数のボタンやリンク要素に書くことが多いですよね。そのたびに@media (hover: hover) and (pointer: fine)を書くのは結構手間です。

ですので、Sassを使っている場合はmixinを作っておくと便利です。

@mixin hover {
  //hoverはPCのみ
  @media (hover: hover) and (pointer: fine)  {
    &:hover {
      @content;
    }
  }
  //IE11対応用
  @media (-ms-high-contrast: none), (-ms-high-contrast: active) {
    &:hover {
      @content;
    }
  }
}

このmixinを作っておくと、以下の@include hoverのように簡単にスタイルを書くことができます。

.button {
  @include hover {
    opacity: 0.7;
  }
}

Sassを使っているプロジェクトでは、このようなmixinを用意しておくとコードの記述量を減らすことができ、保守もしやすくなりますね!

VS Codeのスニペットに登録する (コピペ可)

hover用のmixinを作っておくと便利ですが、さらに効率を上げる方法としてVS Codeのスニペットに登録しておく方法もあります。

スニペットを登録しておけば、決めたキーワードを入力するだけでコードをすぐ呼び出すことができます。

例えば、次のようなスニペットを登録しておくと便利です。

"hover": {
  "prefix": "hov",
  "body": [
    "transition: all 0.3s ease;", //任意
    "",
    "@include hover {",
    "  $1",
    "}",
  ],
  "description": ""
},

これを設定しておくと、hovと入力するだけで次のコードを展開できます。

transition: all 0.3s ease;

@include hover {
  
}

実案件では同じパターンのコードを書くことが多いため、このようにスニペット化しておくとコーディングを効率化できます!

VS Codeのスニペット登録方法

VS Code左下の「歯車アイコン」→「ユーザースニペット」→VS Code上部検索バーに表示される「css.json.code-snippets」の順に進み、登録したいコードを貼り付けます。

VS Codeのスニペット登録方法(Windows) ①
VS Codeのスニペット登録方法(Windows) ①

そうすると、以下の画像のように、hovと打つだけで登録したコードが候補として表示されます。

VS Codeのスニペット登録方法(Windows) ②
VS Codeのスニペット登録方法(Windows) ②

hovではなく別のテキストでもいいですし、transitionに関する記述は私の場合なので、ご自身の可使いやすいようにカスタマイズしていただければと思います。

まとめ

ホバーアクションを:hoverで指定すると、スマホでもタップ時にホバーアクションが発動してしまうため、スマホでは無効化することが望ましいです。(案件の仕様によります)

その際は、画面幅で判定するmax-widthではなく、入力デバイスの特性を判定できるhoverpointerメディアクエリを使う方法が有効です。

また、Sassを使っている場合はmixinを作っておくと、:hoverのスタイルを効率よく管理することができます。

コピペできるコードを利用して、ご自身の使いやすいコードにカスタマイズのうえ、洗練されたUIにしていきましょう!

スポンサーリンク