風柳メモ

ソフトウェア・プログラミング関連の覚書が中心

【覚書】 z-index により手前に来ている透明要素が原因でイベントが発火しないときには、 pointer-events をうまく使う

Twitter 原寸びゅーで、画像クリック時に原寸画像を開くようにしようとして、ギャラリー表示時にはうまくクリックイベントが発火しないことに気が付いた。

原因は(z-index 指定により)画像の手前に透明な要素が存在したため*1
pointer-eventsの設定を行うことで対処できそうということが分かったので、メモ書き。
なお、pointer-events は IE では IE11 以上でサポート(IE10 以下は未サポート)となる。

サンプル




(A)




(B)




(C)


画像(BUTTON)や枠の部分をクリックしたときの動作に違いがある。

覚え書き

目的として、透明要素(枠の部分・"z-index: 1"が指定されている)のクリックイベントは残しつつ、画像をクリックしたときには別のイベントを発火させたい。

  1. 最初は、単に画像にクリックイベントを設定するだけにしていた(A)。
    ところが、実際には手前に来る透明要素(枠)のイベントしか発火しない(なお、サンプルでは、画像(BUTTON)の CSS に "cursor: pointer" を設定してあるが、これも効いていないのが判る)。
  2. 手前に来る要素の CSS に "pointer-events: none" を設定(B)。
    これで、画像をクリックしたときのイベントは発火するようになったが、逆に手前の透明要素(枠)のイベントが発火しなくなってしまう。
  3. 画像を含む要素の z-index 値を、透明要素(枠)のものより大きくし、かつ、CSS に "pointer-events: none" を設定。また、このままだと、画像のイベントも発火しなくなるため、画像の方には "pointer-events: auto" を設定(C)。
    これで、画像と枠それぞれのイベントが発火するようになった。
HTMLソースコード
<div>

    <div style="width: 120px; height: 120px; position: relative; float: left; margin: 5px; background: pink;">
        <div style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: rgba( 0, 0, 0, 0 )">
            <button style="display: block; width: 50%; height: 50%; position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; font-size: 12px; cursor: pointer;" onclick="alert( '画像をクリック' )">画像</button>
        </div>
        <div style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: rgba( 0, 0, 0, 0 ); z-index: 1;" onclick="alert( '枠をクリック')">(A)</div>
    </div>

    <div style="width: 120px; height: 120px; position: relative; float: left; margin: 5px; background: limegreen;">
        <div style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: rgba( 0, 0, 0, 0 )">
            <button style="display: block; width: 50%; height: 50%; position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; font-size: 12px; cursor: pointer;" onclick="alert( '画像をクリック' )">画像</button>
        </div>
        <div style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: rgba( 0, 0, 0, 0 ); z-index: 1; pointer-events: none;" onclick="alert( '枠をクリック')">(B)</div>
    </div>

    <div style="width: 120px; height: 120px; position: relative; float: left; margin: 5px; background: lightblue;">
        <div style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: rgba( 0, 0, 0, 0 ); z-index: 2; pointer-events: none;">
            <button style="display: block; width: 50%; height: 50%; position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; font-size: 12px; cursor: pointer; pointer-events: auto;" onclick="alert( '画像をクリック' )">画像</button>
        </div>
        <div style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; background: rgba( 0, 0, 0, 0 ); z-index: 1;" onclick="alert( '枠をクリック')">(C)</div>
    </div>

    <br style="clear:both;">
</div>

*1:前後移動用のナビで、こちらもクリックイベントが設定されている