ある要素の前面に何か別の要素をかぶせるように配置した時、背面にある要素のマウスイベントは基本的には反応しません。(前面の要素のみ)
当然といえば当然の話なのですが、デザインや仕様によっては、実際に構築するまでこの問題に気付きにくい場合があります。ありました。
下記のサンプルは、透過PNGでできた星画像をリンクボタンにかぶるように position:absolute で配置した例です。見た目の上ではかぶっていませんが、それは星PNGの背景が透過されているからで要素同士はしっかりかぶっているため、背面のリンクボタンにマウスを置いてもカーソルの形は変わりませんし、クリックしても無反応です。(ギリギリかぶっていないリンクボタンの上端と右端は反応する)
これをどうにか前面の星PNGに邪魔されずにリンクボタンをマウスに反応させるようにする、というのがこの記事の本題。
一番簡単なのは、CSSで
.star { pointer-events: none; }
と書いてその名の通り前面になる要素をマウスに反応させなくする方法なんですが、ブラウザの対応状況から考えてとてもクライアントワークでは使えません。そもそもこのプロパティ自体、独自実装なのかな?
で、どうしたもんかと悩んでいたところで、以下のような記事を見つけました。
– 参考ページ: Forwarding Mouse Events Through Layers
前面要素のハンドラで、自身を一瞬消して(display:none)その間に document.elementFromPoint(x,y) から背面要素を取得する、という流れのようです。多分。
なるほど!という事で、早速泥くさい感じで試してみたのが以下のサンプル。
とりあえず各主要ブラウザのほか、IE6やiPhoneでも動いているようです。(IE6は透過されませんが)
ただ、上記のサンプルが意図した通り動いているのはたまたまで、 document.elementFromPoint は実装によって挙動が異なるので、実際はもっとちゃんと書かないと破綻してしまう可能性大。iPhoneも拡大したりすると動かない。
– 参考ページ: 要素が画面上に見えているかどうかを調べる – by edvakf in hatena
記事タイトルが示す結果とは違うけど、とりあえず解決のメドがついたのでよしとしたいと思います。もっと根本的な解決方法をご存知の方がいましたら教えて下さいませ。
Flashなら target.mouseEnabled=false で済むから簡単なんだけどなあ…。