CSSでのホバー時のスタイルの適用はany-hoverメディア特製で指定すると良い



Web制作でWebデザインを作っていく中で、ページのさまざまな要素にアニメーションを含んだ変化を加えるために、hoverアクションを実装することはよくあるでしょう。

hoverアクションはCSSの:hover擬似クラスで手軽に実装できますが、タッチデバイスでhoverアクションを用いると、タッチした後にhover状態となってしまい予期せぬ動作を起こすことがあります。

例えば、ボタンデザインのリンクやテキストリンク、バナーリンク、サムネイルリンクなどでよくhoverアクションで変化を加えることがありますが、タッチ後にhover状態となることで、ユーザーが1タップでページ遷移するはずが動作せず、2タップで動作するなど正常に動かなかったりするので、ユーザー体験(UX)に影響が出てしまいます。

タッチ操作が正常に動作しないことでスムーズにページ遷移などができないと、その後の機会損失に繋がることもありますので、モバイルデバイスにもしっかりと対応しておきたいところです。

PCやスマートフォン、タブレット端末と、様々なデバイスをユーザーが利用する中、ここではhover関連のメディア特性を利用してhoverが動作するデバイスを判別し、hoverが動作するデバイスに対してだけhoverアクションを実装する方法についてご紹介します。

hoverメディア特性には、hoverany-hoverの2種類があります。

@media (hover: hover) / @media (hover: none)
主な入力デバイスがhoverに対応しているかを検査する

@media (any-hover: hover) / @media (any-hover: none)
入力デバイスのいずれかにhoverに対応している入力デバイスが含まれているかを検査する


どちらもhoverが動作するデバイスを判別する部分は同じですが、any-hoverの方がユーザーの環境に合わせて細かく判別することができます。

例えば、スマートフォンやタブレット端末はタッチデバイスですのでhoverが動作しないデバイスと判別されますが、タブレット端末でマウスやトラックパッド付きのキーボードを接続した場合、(any-hover: hover)ではhoverが動作するデバイスと判別してくれます。逆に(hover: hover)では適用されません。
ユーザーの環境に合わせて細かく判別するためには、any-hoverメディア特製を利用していくといいでしょう。

気になるWebブラウザのサポート状況ですが、主要ブラウザはすべてサポートされていますので問題なく利用できます。

Can I use (CSS at-rule: @media: hover)
https://caniuse.com/mdn-css_at-rules_media_hover

Can I use (CSS at-rule: @media: any-hover)
https://caniuse.com/mdn-css_at-rules_media_any-hover

any-hoverメディア特製の利用


ここからは、any-hoverメディア特製の使い方について、よくホバーで変化を加えるボタンデザインのリンクをサンプルにご紹介します。

まずはHTML。

HTML

<a href="#">Button</a>



続いてCSS。
CSSでは、a要素に対するシンプルなボタンのスタイルの指定と、hoverが動作するデバイスに対するメディア特製の記述となります。

CSS

a {
  display: block;
  width: fit-content;
  margin: 1.25rem 0;
  margin-inline: auto;
  padding: 0.5rem 1.25rem;
  color: #333;
  text-decoration: none;
  font-size: 1.25rem;
  font-weight: bold;
  background-color: #ccc;
  border-radius: 0.625rem;
  transition: all .3s ease;
}

@media (any-hover: hover) {
  a:hover {
    color: #fff;
    background-color: #111;
  }
}



アットルールによる定義規則では「@media (any-hover: hover)」として、メディア特製を使ってhoverが動作するデバイスに対してスタイルを適用させます。

CSSは以下のようにネスト(入れ子)で記述することもできます。

CSS

a {
  display: block;
  width: fit-content;
  margin: 1.25rem 0;
  margin-inline: auto;
  padding: 0.5rem 1.25rem;
  color: #333;
  text-decoration: none;
  font-size: 1.25rem;
  font-weight: bold;
  background-color: #ccc;
  border-radius: 0.625rem;
  transition: all .3s ease;
  @media (any-hover: hover) {
    &:hover {
      color: #fff;
      background-color: #111;
    }
  }
}


any-hoverの値には、hoverまたはnoneが指定できますが、hoverとする場合は「@media (any-hover)」としても同じく動作します。

PCのWebブラウザでアクセスすると、対象要素のhover時にスタイルが適用されます。
Webブラウザのデベロッパーツールからも、hoverを有効にした時にスタイルが適用されているのが確認できます。

any-hoverメディア特製によるホバーの動作



スマートフォンやタブレット端末の動作については実機で確認するのが一番ですが、PCでもWebブラウザのデベロッパーツールを使えば動作確認は可能です。
デベロッパーツールをレスポンシブモードで表示して、画面右上の矢印アイコンから「Add device type」を選択します。

Webブラウザのデベロッパーツールのレスポンシブモードでdevicetypeを表示する



デバイスタイプの設定項目が表示されますので、Mobileを設定することでスマートフォンやタブレット端末のモバイルデバイスのタッチ操作に変更できます。
マウスやトラックパッド付きのキーボードを接続したデバイスの動作は、Mobile(no touch)を設定することで確認できます。

Webブラウザのデベロッパーツールを使ったMobileのタッチ動作の確認



Mobile(no touch)に設定した場合、PCと同じようにマウスポインタが表示されhoverが動作します。

Webブラウザのデベロッパーツールを使ったMobileのマウス操作の確認



デベロッパーツールで確認できるもののPCで動作するものですので、スマートフォンやタブレット端末の動作の最終チェックはなるべく実機で確認できるといいでしょう。

JavaScriptでも制御可能


JavaScriptを利用することがある場合は、matchMediaメソッドを使ってもhover動作の制御できます。
matchMediaメソッドは指定したメディア特製のパース結果を表し、MediaQueryListオブジェクトを返します。

試しに、動作確認としてのプログラムを実装してみます。
まずはHTMLとCSS。

HTML

<a href="#" id="btn">Button</a>

CSS

a {
  display: block;
  width: fit-content;
  margin: 1.25rem 0;
  margin-inline: auto;
  padding: 0.5rem 1.25rem;
  color: #333;
  text-decoration: none;
  font-size: 1.25rem;
  font-weight: bold;
  background-color: #ccc;
  border-radius: 0.625rem;
  transition: all .3s ease;
}


HTMLでは、JavaScriptの実装を確認するために、ボタンリンクにidを付与しておきました。
CSSではメディア特製は使わず、JavaScriptで判別していきます。

続いてJavaScript。
変数またはconst定数などで、デバイスのhover動作環境や対象の要素を管理して処理していきます。
以下、サンプルコードになります。

JavaScript

const hasHover = window.matchMedia("(any-hover: hover)").matches;
const btn = document.getElementById("btn");
if(hasHover) {
  btn.innerHTML = "Click";
  btn.addEventListener('mouseover',() => {
    btn.style.color = '#fff';
    btn.style.backgroundColor = '#111';
  }), btn.addEventListener('mouseout',() => {
    btn.style.color = '';
    btn.style.backgroundColor = '';
  });
} else {
  btn.innerHTML = "Tap";
}


「window.matchMedia(“(any-hover: hover)”).matches」では、matchMediaメソッドのMediaQueryListEventインターフェイスの情報をmatchesプロパティでチェックしています。matchesプロパティはtrueまたはfalseの論理値を返すので、この論理値をif文の条件として処理します。

PCなどhoverが動作するデバイスでは、addEventListenerメソッドでmouseoverイベントを使用して、ボタンのテキスト色や背景色を変更します。また、mouseoutイベントで要素からマウスが離れた時はプロパティに対する値を空にして、CSSで指定しているボタンのデザインに戻します。
スマートフォンやタブレット端末はタッチ操作となり、hoverが動作しないデバイスですのでmouseoverイベントは実装されません。ただ、タブレット端末でマウスやトラックパッド付きのキーボードを接続した状態では、hoverが動作するのでmouseoverイベントが実装されます。

以下、デベロッパーツールでのDesktop、Mobile、Mobile(no touch)の動作確認です。

Webブラウザのデベロッパーツールを使ったPC、スマートフォン、タブレット端末の動作確認



ちなみに、matchMediaメソッドの引数は「”(any-hover)”」としても同じく動作します。

最後に


hoverアクションはスマートフォンやタブレット端末など、タッチ操作のモバイルデバイスでうまく動作しないことがあります。
hover関連のメディア特製を利用することで、デバイスに合わせてhoverアクションの適用することができます。
モバイルデバイスのマウスやキーボードの接続を含め、ユーザーの環境にしっかり適用できるようany-hoverメディア特製を利用してみてください。