CSS
 Computer >> コンピューター >  >> プログラミング >> CSS

CSSのpointer-eventsプロパティで特定要素のホバー・マウスオーバーイベントを無効化する方法

CSSのpointer-eventsプロパティを活用すれば、特定のHTML要素でマウスオーバー(:hover)イベントを無視・無効化できます。本記事では、実際のWeb制作で遭遇したホバー問題を例に、その解決方法を段階的に解説します。

最近、クライアント向けにチーム紹介ギャラリーページを制作しました。各ギャラリーアイテムはUIカードで表現されており、カードの上にマウスを乗せるとオーバーレイの色が変化する仕組みです。しかし開発中に予期しない問題に直面し、それがこのチュートリアルを書くきっかけとなりました。

UIカードの内容と構造

各ギャラリーカードは、次の要素で構成されています。

  • 従業員の写真(白黒)
  • 従業員名(白文字)
  • 従業員の役職(白文字)
  • 控えめな暗色の背景オーバーレイ

ユーザーがカードの上にマウスを乗せると、背景オーバーレイが明るい半透明の黄色(ブランドカラー)へと滑らかにトランジションします。

UIカードの実例

本チュートリアルでは問題の解決に焦点を絞るため、UIカードをデザイン面で簡略化したバージョンを用意しました。カードの上にマウスを乗せて、背景色が明るい黄色へ変化することを確認してみてください。

CSSのpointer-eventsプロパティで特定要素のホバー・マウスオーバーイベントを無効化する方法
従業員名
役職

しかし、ここに問題があります。もうお気づきの方もいるかもしれません。テキスト部分の上にマウスを移動してみてください。何が起こるでしょうか?

マウスがテキスト要素の上に移動した瞬間、ホバーイベントがキャンセルされ、黄色から即座にデフォルトの非アクティブ状態(グレー)へ戻ってしまいます。これは許容できません。

以下がHTMLコードです。

<div class="card">
  <div class="card-overlay"></div>
  <img
    class="card-image"
    src="https://jp.wsxdn.com/UploadFiles_5590/202203/2022033109324298.jpg"
  />
  <div class="card-info">
    <div class="card-name">Employee Name</div>
    <div class="card-role">Employee Role</div>
  </div>
</div>

続いてCSSです。

.card {
  max-width: 350px;
  position: relative;
}

.card-overlay {
  background-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.5));
  height: 100%;
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
  transition: background-color 0.6s;
}

.card-overlay:hover {
  background-color: rgba(255, 204, 7, 0.5);
}

.card-image {
  max-width: 100%;
  display: block;
}

.card-info {
  position: absolute;
  bottom: 2rem;
  left: 2rem;
}

.card-name,
.card-role {
  color: white;
  font-size: 1.5rem;
  line-height: 1.25;
  padding: 0.25rem;
}

.card-name {
  font-weight: bold;
}

では、なぜテキスト部分にマウスを乗せるとホバーイベントがキャンセルされるのでしょうか?

原因はHTMLのスタッキング順序(重なり順)にあります。スタッキング順序は通常、CSSのz-indexプロパティで制御されます。しかし、CSSで明示的に指定しない場合、デフォルトのスタッキング順序が適用されるのです。

z-index重なり順を制御するCSSプロパティです。positionの値が同じ要素同士では、z-indexの値(数値)が最も大きい要素が他の要素より前面に配置されます。Webページ上のすべての要素のデフォルトのz-index値はautoで、これは0と同じ扱いになります。

今回のケースでは、2つの要素がどちらも絶対配置(absolute)で、どちらもデフォルトのz-index: auto(0)です。この場合、どちらが前面に来るのでしょうか(どちらかが勝たなければなりません)。

答えは、HTML内で後に記述された要素が勝ちます。

今回の場合、名前と役職のテキスト要素を含む<div class="card-info">コンテナが、card-overlay要素の後に記述されています。

<div class="card">
  <div class="card-overlay"></div>
  <img
    class="card-image"
    src="https://jp.wsxdn.com/UploadFiles_5590/202203/2022033109324298.jpg"
  />
  <div class="card-info">
    <div class="card-name">Employee Name</div>
    <div class="card-role">Employee Role</div>
  </div>
</div>

つまりUIカードの例では、マウスがテキスト要素の上に移動した時点で、オーバーレイ要素ではなくcard-info要素をホバーすることになります。しかし、:hover(疑似クラス)が設定されているのは.card-overlayだけです(前述のCSSコードを参照)。

では、どうすればよいのでしょうか?

対処法①:HTMLの記述順を入れ替える

<div class="card-overlay"></div>要素を物理的に<div class="card-info">...</div>要素の後ろへ移動させてみましょう。

<div class="card">
  <img
    class="card-image"
    src="https://jp.wsxdn.com/UploadFiles_5590/202203/2022033109324298.jpg"
  />
  <div class="card-info">
    <div class="card-name">Employee Name</div>
    <div class="card-role">Employee Role</div>
  </div>
  <div class="card-overlay"></div>
</div>

するとスタッキング順序が入れ替わり、次のようになります。

CSSのpointer-eventsプロパティで特定要素のホバー・マウスオーバーイベントを無効化する方法
従業員名
役職

これでテキスト部分の上にマウスを乗せても、オーバーレイのトランジションが中断されなくなりました(実際に試してみてください)。

しかし、待ってください。今度はスタッキング順序が入れ替わったことで、オーバーレイがテキスト要素の前面に配置され、テキストがオーバーレイによってグレーがかってしまいました。

一つの問題を解決したと思ったら、別の問題を生み出してしまったのです。

この手法は使わないことにして、<div class="card-overlay">要素を元の位置へ戻しましょう。

対処法②:z-indexを指定する

では、.card-overlayクラスにz-index: 1を指定したらどうなるでしょうか?

これでcard-overlayは、デフォルトのz-index: 0のままのcard-infoよりも高い重なり順を持つため、前面に配置されます。ホバー時の色変化も再び中断されずに機能するようになります。しかし……

残念ながら、この方法の結果は、先ほどHTMLの記述順を入れ替えた場合とまったく同じです。今回はCSSで直接スタッキング順序を変更しただけで、テキスト要素は依然としてオーバーレイによってグレーがかったままです。

これではやはり許容できません!

pointer-eventsで問題を解決!

そこでふと思い出したのが、CSSには要素がポインターイベントに反応するかどうかを制御できるpointer-eventsというプロパティが存在するということです。

ポインターイベントとは、クリック、スクロール、要素の上へのマウス移動(ホバー)など、マウスに関わるすべての操作を指します。

そこで、.card-infoクラスにpointer-events: none;を追加しました。

.card-info {
  position: absolute;
  bottom: 2rem;
  left: 2rem;
  pointer-events: none; /* これが解決策! */
}

これで、テキスト部分を含むUIカード全体をホバーしても、ホバーイベントがキャンセルされなくなりました。さらに、テキスト要素は100%の白色を保ったまま表示されます。

CSSのpointer-eventsプロパティで特定要素のホバー・マウスオーバーイベントを無効化する方法
従業員名
役職

コード全体はCodePenでも確認できます。

  1. CSSでcontenteditable要素の境界線(枠線)を削除する方法

    HTMLのcontenteditable属性を指定した要素は、ブラウザ上で直接テキストを編集できます。しかし、要素をクリックして編集モードにすると、多くのブラウザではデフォルトで青い枠線(アウトライン)が自動的に表示されます。この境界線を非表示にしたい場合は、CSSのoutlineプロパティを使用します。[contenteditable]セレクターに対してoutline: 0px solid transparent;を指定することで、編集時の枠線をきれいに取り除くことができます。コード例<!DOCTYPE html> <html> <head> <st

  2. CSSでホバー時にトランジション(アニメーション)を追加する方法を解説

    CSSでホバー時にトランジション(滑らかなアニメーション効果)を追加するには、transitionプロパティと:hover疑似クラスを組み合わせて使用します。あらかじめ要素にtransitionを設定しておくことで、ホバー時の変化が瞬時に切り替わるのではなく、指定した時間をかけてスムーズに変化するようになります。 サンプルコード <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1&q