CSS

pointer-events lets you switch whether an element can be targeted by mouse/touch/pointer actions, so overlays or decorations don’t block clicks and the element behind can still be interacted with.

pointer-events

pointer-events は「この要素は“クリック(タップ)対象になれる?それとも、触れない存在にする?”を切り替えるCSS」です。見た目はそのまま残しつつ、操作だけを通したり止めたりできるので、オーバーレイや装飾レイヤーが邪魔になる場面で特に効きます。

まずは感覚:これは「触れる判定(ヒットテスト)」のスイッチ

ブラウザはクリックされた座標に対して「どの要素がクリック対象か」を判断し、その要素をイベントのターゲットにします。この“ターゲット選び”の段階で、pointer-events は効きます。

pointer-events: auto;
通常どおり。クリック対象になれる。
pointer-events: none;
クリック対象にならない。クリックは「背後」に通る。

「透明にする(opacity: 0)」や「隠す(display: none)」と違い、pointer-events見た目を残したまま操作だけ切る のが得意です。

よくある用途:オーバーレイや飾りがクリックを邪魔するのを防ぐ

いちばん多いのはこれです。「上に乗せた飾り(疑似要素や半透明の膜)が、下のリンクのクリックを吸ってしまう」問題。

HTML

<div class="demoCard">
    <a href="#">カードのリンク(クリックできる想定)</a>
    <div class="demoOverlay" aria-hidden="true"></div>
</div>

CSS

.demoCard {
    position: relative;
}

.demoOverlay {
    position: absolute;
    inset: 0;

    /* 見た目はあるけど、触れない飾りにする */
    pointer-events: none;
}

ここで覚えるコツ

最小の書き方(まずこれだけでOK)

HTML要素で実用上まず覚えるのは、autonone の2つが中心です。

CSS

.decoration {
    pointer-events: none;
}

これだけで「見た目は残したまま、クリックは下へ通す」が作れます。

「親は触れない、子だけ触れる」ができる(チュートリアルで超便利)

“膜”は触れないけど、膜の上にあるボタンだけ押せる、という構成ができます。

背後の操作は通したいけど、ここだけ押せる…みたいな場面を想像してください。

HTML

<div class="tutor">
    <button class="tutorButton" type="button">ここだけ押せる</button>
    <div class="tutorOverlay" aria-hidden="true"></div>
</div>

CSS

.tutor {
    position: relative;
}

.tutorOverlay {
    position: absolute;
    inset: 0;

    /* 基本は全部“触れない膜” */
    pointer-events: none;
}

.tutorButton {
    /* この要素だけ“触れる” */
    pointer-events: auto;
}

ただし注意(実務メモ)

混同しやすいもの:透明・非表示・重なりとの違い

クリック問題のデバッグで迷子になりやすいので、ここは先に整理しておくと強いです。

opacity: 0
見えないけど“そこにいる”。クリックを吸います。「見えないのに押せない」の典型原因。
visibility: hidden
見えないし、基本は操作もできない。レイアウト上の場所は残ります。
display: none
要素そのものが消える(レイアウトにも影響)。
z-index
重なり順を変えるもの。クリックが吸われる原因が「上に乗っている」なら解決することもありますが、「上に置きたい(見た目の都合)」場合は pointer-events のほうが素直なことが多いです。

落とし穴:キーボード操作(Tab/Enter)とは別ルート

pointer-events は、あくまでポインター入力(マウス・タッチ・ペン)に関する“当たり判定”です。なので、次のことが起きえます。

「本当に無効化したい」のか、「クリックだけ止めたい」のかで、対策が変わります。

ボタンなら disabled が第一候補

HTML

<button type="button" disabled>
    処理中…
</button>

リンクやdiv相当は「伝える」と「止める」を分けて考える

つまり、pointer-events は「クリック停止の部品」。無効化の完成形にするには、周辺の設計も一緒に整えるのが実務です。

実務でよく使うパターン集(短く、でも使える)

1) 疑似要素がクリックを吸うのを防ぐ

CSS

.button::before {
    content: "";
    position: absolute;
    inset: 0;

    /* 飾りは触らせない */
    pointer-events: none;
}

2) ドラッグ中だけクリックを止める(クラス切り替え)

CSS

.isDragging {
    pointer-events: none;
}

JSでドラッグ開始時に isDragging を付け、終了で外す…のように使います。ドラッグ中の誤クリックを減らすのに効きます。

3) 無効化“っぽい”見た目(※本当に無効にしたい場合は前の節へ)

CSS

.isDisabledLike {
    pointer-events: none;
    opacity: 0.55;
    cursor: not-allowed;
}

上級者向け:デバッグの考え方(イベント伝播ではなく“ターゲット選び”)

pointer-events は「イベントがDOMツリーをどう伝わるか(バブリング/キャプチャ)」を変えるというより、ターゲットに選ばれるかどうか を変えます。ここを押さえると、原因切り分けが速くなります。

デバッグのコツ

SVGで値が増える理由(必要になったらここが効く)

HTML要素では auto / none が主役ですが、SVGでは「塗り(fill)だけ当たり判定」「線(stroke)だけ当たり判定」など、より細かい制御が必要になることがあります。

実務メモ(深入りしすぎない版)

FAQ

Q. pointer-events: none; にすると何が起きますか?
A. その要素はクリック(タップ)の対象に選ばれなくなり、クリックは背後の要素に通ります。見た目は残るので「見えるけど触れない」が作れます。
Q. 透明(opacity: 0)なのにクリックを邪魔するのはなぜ?
A. 透明でも要素は“そこにある”のでクリック対象になります。クリックを通したいなら pointer-events: none を検討します。
Q. 親に none を付けたら、子も全部押せなくなりますか?
A. 基本は押せなくなりがちですが、子に pointer-events: auto を付けて「子だけ押せる」にできるケースがあります(オーバーレイ+ボタンなど)。
Q. “無効化”したいだけならこれでOK?
A. クリックだけ止めるならOKですが、Tab移動や支援技術に対しては別ルートです。ボタンなら disabled、それ以外は aria-disabled とJSガードも検討してください。
Q. スマホのタップでも同じですか?
A. 基本は同じで、ポインター入力(マウス/タッチ/ペン)に効きます。スクロールやジェスチャー制御は touch-action 側の影響も受けます。

よくあるエラー早見表

見えないのにクリックできない
opacity: 0 の要素が上に残っている可能性。不要なら消す、消せないなら pointer-events: none を付けてクリックを通します。
装飾(疑似要素)がクリックを吸ってしまう
::before/::after に当たり判定があることが多いです。疑似要素側に pointer-events: none を付けます。
無効化したのにTabで選べてしまう
pointer-events はクリック系だけ。disabled / aria-disabled / tabindex / JSガードを検討します。
クリックが通るせいで誤操作が増えた
「通す」設計がUXに合っていない可能性。通す範囲を狭める、または通さずに「閉じる」導線を用意します。
iframeの上で思った通りにならない
iframeは挙動が難しくなりがちです。重ねない構成に寄せるほうが堅いです。