pointer-events: none; を使いこなそう

2025/03/13

pointer-events: none; を使いこなそう

業務でフロントエンドの実装をしている時に知ったpointer-events: none; について解説したいと思います。

pointer-events: none; とは?

簡単に言うと、「この要素はクリックやタップなどの操作を受け付けませんよ」というCSSのプロパティです。

スマホフィルムの上から画面をタップしても問題なく反応しますよね?それと似たようなイメージです。

要素を重ねたときの操作阻害

Webサイトやアプリケーションを開発していると、要素を重ねて配置する場面が多々あります。例えば、以下のようなケースが考えられます。

モーダルウィンドウ

  • 画面全体を覆うように表示されるモーダルウィンドウは、背後のコンテンツの上に重ねて表示されます

ドロップダウンメニュー

  • メニューボタンをクリックすると選択肢がリストとして表示されるドロップダウンメニューは、ボタンの上に重ねて表示されます

オーバーレイ

  • 画像の上にテキストやアイコンを重ねて表示することで、視覚的な効果を高めることができます

これらの要素を重ねて配置する際、問題となるのが誤操作、そして「本来押したい要素の上に重ねてしまったことでそれが押せない」といった操作阻害です。例えば、

  • モーダルウィンドウを閉じるつもりが、背後のコンテンツをクリックしてしまった
  • ドロップダウンメニューの選択肢を選ぼうとして、誤ってメニューボタンをクリックしてしまった
  • 本来クリックしたいボタンの上に半透明の要素が重なっており、クリックできない

などが挙げられます。

私の体験談

ドロップダウンメニューの右端に、視覚的にタップできることを示すために▼アイコンをabsoluteで配置しました。見た目は完璧でしたが、実際に操作してみると、▼アイコンがある部分をタップしてもメニューが開かないという問題が発生しました。

原因は、▼アイコンがメニューボタンの上に重なっており、本来クリックしたいメニューボタンのクリックイベントが阻害されていたのです。

このような誤操作や操作阻害を防ぐために、pointer-events: none;が役立ちました。

pointer-events: none; をどのように活用するのか

▼アイコンの要素に対してpointer-events: none;のスタイルを適用するだけで、背後のメニューボタンが反応するようになりました。サンプルコードは以下です(jsFiddleで動作が確認できます)。

<div class="dropdown">
  <button class="dropdown-toggle">選択してください</button>
  <svg class="dropdown-arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <path d="M7 10l5 5 5-5z"/>
  </svg>
  <ul class="dropdown-menu">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>
const dropdownToggle = document.querySelector('.dropdown-toggle');
const dropdownMenu = document.querySelector('.dropdown-menu');

dropdownToggle.addEventListener('click', () => {
  if (dropdownMenu.style.display === 'block') {
    dropdownMenu.style.display = 'none';
  } else {
    dropdownMenu.style.display = 'block';
  }
});
.dropdown {
  position: relative; /* 子要素の基準となるように設定 */
  display: inline-block;
  width: 100%;
}

.dropdown-toggle {
  padding: 10px 20px;
  border: 1px solid #ccc;
  cursor: pointer;
  width: 100%;
}

.dropdown-arrow {
  position: absolute; /* 親要素を基準に配置 */
  top: 50%;
  right: 10px;
  transform: translateY(-50%); /* 垂直方向に中央揃え */
  width: 40px; /* SVG のサイズ調整 */
  height: 40px; /* SVG のサイズ調整 */
  fill: #333; /* SVG の色 */
  pointer-events: none;
}

.dropdown-menu {
  list-style: none;
  padding: 0;
  margin: 0;
  border: 1px solid #ccc;
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  display: none; /* 初期状態では非表示 */
}

.dropdown:hover .dropdown-menu {
  display: block; /* ホバー時に表示 */
}

.dropdown-menu li {
  padding: 10px;
  cursor: pointer;
}

.dropdown-menu li:hover {
  background-color: #f0f0f0;
}

最後に

pointer-events: none;の紹介でした。要素の重なりによる誤操作や操作阻害に悩まされた際は、ぜひこのプロパティを活用してみてください。

補足

pointer-events: none; を適用した要素の子要素に対しても、プロパティは適用されます。子要素の操作を有効にしたい場合は、子要素に pointer-events: auto; を指定してください。

\ シェアする /

この記事を書いた人

プロフィール画像

1996年生まれ。中部大学大学院にてコンピュータビジョン関連の深層学習の研究に注力したのち、2021年4月に株式会社medibaに入社。 KDDIグループ企業各社のDeveloperが集い、エンジニアが楽しめるイベントを提供するコミュニティ「KGDC」のイベント運営も行っています。

記事に関する質問は、フッター掲載の各種SNSにてお問い合わせください。