CSS の pointer-events プロパティを使うと、要素がマウスのクリックやホバーに反応するかどうかを制御できます。「JavaScript を書かずにボタンを押せない状態にしたい」「上に重なった要素を透過させて下の要素をクリックさせたい」といった場面で役立ちます。この記事では、pointer-events: none と auto を中心に、基本的な使い方から実践的な使いどころ、つまずきやすいポイントまでを解説します。フロントエンドを触り始めた初心者〜中級者の方を対象にしています。
目次
pointer-events で何ができるのか
pointer-events は、その要素が「マウスポインターの操作対象になるかどうか」を決めるプロパティです。ここでいうポインター操作とは、クリック、ホバー(マウスを乗せること)、そして :hover や :active といった擬似クラスの発火などを指します。
pointer-events: none を指定すると、その要素はマウス操作を一切受け付けなくなります。ボタンに指定すればクリックできなくなり、リンクに指定すれば押しても遷移しなくなります。ホバー時の見た目の変化も止まります。逆に auto は通常どおり反応する状態、つまり初期値です。
まずは実際に動く例を見てみましょう。次のデモでは、ボタンAは通常のボタン、ボタンBには pointer-events: none を指定しています。CSS を書き換えて挙動の違いを確かめてみてください。
<div class="panel">
<p>ボタンAは通常どおり押せます。ボタンBは pointer-events: none で無効化しています。</p>
<button class="btn btn--active" type="button">ボタンA(押せる)</button>
<button class="btn btn--disabled" type="button">ボタンB(押せない)</button>
</div>
.panel {
font-family: sans-serif;
padding: 8px;
}
.btn {
display: inline-block;
margin: 8px 8px 0 0;
padding: 10px 20px;
border: none;
border-radius: 6px;
background: #007bff;
color: #fff;
font-size: 15px;
cursor: pointer;
}
/* ホバーで色が変わる(押せるボタン) */
.btn--active:hover {
background: #0056b3;
}
/* pointer-events: none でクリックもホバーも無効化 */
.btn--disabled {
pointer-events: none; /* マウス操作を一切受け付けない */
background: #b0b0b0; /* 見た目でも無効と分かるように */
cursor: default;
}
/* 無効ボタンはホバーしても色が変わらない */
.btn--disabled:hover {
background: #ff0000;
}
ボタンBはマウスを乗せてもカーソルの形が変わらず、クリックしても反応しません。:hover で赤色に変えるルールを書いていても、ポインターイベント自体が届かないため色は変化しません。これが pointer-events: none の効果です。
基本の使い方(none と auto)
使い方はとてもシンプルで、無効化したい要素に pointer-events: none; を指定するだけです。次のように状態を表すクラスと組み合わせて切り替えるのが一般的です。
/* クリックできない状態 */
.button.is-disabled {
pointer-events: none;
opacity: 0.5; /* 見た目でも無効だと分かるようにする */
}
/* 通常の状態(初期値なので明示しなくてもよい) */
.button {
pointer-events: auto;
}
ポイントは、無効化するときに opacity などで見た目も変えておくことです。pointer-events: none は挙動を止めるだけで、見た目は変えません。そのため見た目そのままだと「押せそうなのに押せない」状態になり、ユーザーが混乱します。
また、いったん親要素で none を指定した中の一部だけを反応させたいときは、その子要素に auto を指定して打ち消せます。この上書きができるのが auto の便利なところです。
/* オーバーレイ全体はクリックを透過させる */
.overlay {
pointer-events: none;
}
/* ただし中の閉じるボタンだけは押せるようにする */
.overlay .close-button {
pointer-events: auto;
}
指定できる主な値と意味
HTML 要素で日常的に使うのは auto と none の 2 つですが、pointer-events には SVG 向けの値も定義されています。よく使う値を中心に整理すると次のとおりです。
| 値 | 意味 |
|---|---|
auto | 初期値。要素は通常どおりクリック・ホバーに反応する |
none | 要素がポインターイベントの対象にならない。クリック・ホバーが無効になり、下の要素へ透過する |
visiblePainted | SVG 用。表示されていて、かつ塗り(fill)や線(stroke)が描画されている部分だけが反応する |
fill | SVG 用。塗りの領域だけが反応する |
stroke | SVG 用。線の領域だけが反応する |
all | SVG 用。塗り・線・領域内すべてが反応する |
visiblePainted や fill などは SVG の図形に対して「どの部分をクリック判定にするか」を細かく決めるための値です。通常の div や button といった HTML 要素を扱う分には、auto と none の 2 つを覚えておけば十分です。
重なった要素のクリックを下に通す
pointer-events: none の特徴的な使いどころが「クリックを下の要素に透過させる」ことです。要素が反応対象から外れると、その要素の上でクリックしたときに、ブラウザはあたかもその要素が存在しないかのように、真下にある要素へイベントを届けます。
たとえば、地図の上に案内テキストを重ねて表示しつつ、その上でのドラッグ操作は地図側に届けたい、といった場面です。テキストのレイヤーに pointer-events: none を指定すれば、見た目は前面に出したまま、マウス操作は下の地図に通せます。
.map {
position: relative;
}
/* 地図の上に重ねる注釈レイヤー */
.map__annotation {
position: absolute;
inset: 0;
/* クリックやドラッグは下の地図に通す */
pointer-events: none;
}
装飾のために全面に敷いたグラデーションやアイコンが、下のボタンのクリックを邪魔してしまうことがあります。そうした「見せたいだけで操作させたくない」要素にも pointer-events: none が有効です。
disabled 属性との違いに注意する
ボタンを押せなくするだけなら、<button> の disabled 属性でも実現できます。ただし両者は仕組みが違うため、使い分けが必要です。
キーボード操作は止まらない
pointer-events: none はあくまで「ポインター(マウスやタッチ)」の操作を止めるものです。キーボードの Tab でフォーカスを当て、Enter キーで実行する、といった操作は止まりません。フォーム部品を本当に無効にしたいときは、HTML の disabled 属性を使うのが基本です。disabled はキーボード操作もフォーカスも無効にし、送信時にその値をサーバーへ送りません。
アクセシビリティへの配慮
見た目だけ無効にして pointer-events: none でクリックを止めても、スクリーンリーダーなどの支援技術には「押せるボタン」として伝わってしまいます。フォーム上のボタンやリンクを無効化する目的なら、CSS だけで済ませず、disabled 属性や aria-disabled="true" を併用して、状態を正しく伝えるようにしましょう。pointer-events は、あくまで見た目の演出や、装飾レイヤーの透過といった用途に向いています。
pointer-events: none が効かないとき
指定したのにクリックが止まらない、あるいは意図せず子要素まで反応しなくなった、というときに確認したい点をまとめます。
子要素にも継承のように波及する
親要素に pointer-events: none を指定すると、その中の子要素も基本的に反応しなくなります。「一部のリンクだけ押せなくしたいのに、周りのボタンまで押せなくなった」という場合は、指定した要素の範囲が広すぎないかを確認してください。特定の子要素だけ復活させたいときは、前述のとおりその子に pointer-events: auto を指定します。
重なり順(z-index)と勘違いしている
「ボタンが押せない」原因が、実は別の透明な要素が上に重なっているケースもあります。この場合、押したいボタン側ではなく、上に重なっている要素の方に pointer-events: none を指定するとクリックが通ります。開発者ツールの要素の検証で、クリック位置に何が乗っているかを確認すると原因を切り分けやすくなります。
JavaScript のイベントも止まる
pointer-events: none を指定した要素では、click や mouseover といった JavaScript のマウスイベントも発火しなくなります。addEventListener で登録したクリック処理が動かないときは、その要素やその親に pointer-events: none が当たっていないかを疑ってみてください。
まとめ
pointer-events は、要素がマウス操作に反応するかどうかを CSS だけで切り替えられるプロパティです。none でクリック・ホバーを無効化し、下の要素へイベントを透過させることができ、auto でその挙動を元に戻したり、一部だけ復活させたりできます。SVG 向けの値もありますが、HTML 要素では none と auto の 2 つを押さえておけば十分です。一方で、キーボード操作は止まらず支援技術には無効と伝わらないため、フォーム部品を本当に無効化したいときは disabled 属性を使う、という使い分けを意識しておきましょう。