[CSS]子要素のホバー時などに親や兄弟(兄)要素を操作出来る”pointer-events”テクニック
こんにちは、ma-ya’s CREATE[まーやずくりえいと]です。
少し前に目からウロコなCSSのpointer-eventsプロパティテクニックが紹介されてたんですが、ずっと記事にしてなかったので記しておきます。
目からウロコ!ホバー時などに子要素をトリガーにして親要素や兄弟(兄)要素のスタイルをCSSだけで変更する
とりあえずは↓のcodepenを触ってみて下さい。
ご覧の通りデモではJSを使っていません。HTML / CSSのみでの実装となってます。
HTMLは親要素(parent)と子要素2つ。childクラスとその直前に記述された兄弟(兄)要素の<p>です。
お わ か り い た だ け た だ ろ う か …
CSSでは親や兄要素のセレクタ指定が出来ない
親が指定出来ないのはもちろん、僕が知る限り現状CSS3では兄要素(自分より前に記述された兄弟要素)を指定するセレクタも無いと思います。
将来的には(CSS Selectors Level 4で)そういったことも可能なセレクタが出てくるようですが、普及するのはまだ先になりそう。
というわけでこういう時はJS(jQuery)でサクッと親や兄要素を検索・指定するのが一般的かと思われます。
と思ってたんですが、ここへ来て朗報が…!!
pointer-eventsのテクニックで似たようなことが出来る模様。
pointer-eventsの意外な仕様
MDNにはこういう記載があります。
pointer-events:none;
要素がマウスイベントの target になることはありません。しかし、子孫要素が pointer-events の別の値をセットされていた場合は、その子孫要素自体はマウスイベントのターゲットとなりえます。その場合、マウスイベントはイベントキャプチャ/バブリングの過程で必要に応じて親要素のイベントリスナーをトリガーします。(MDN)
うん、よくわからない。
しかしデモを見て触った後であれば、何となく言ってることがわかるかと思います。
実装のポイント
- 親要素にpointer-events:none;
- 子要素(トリガーとしたい要素)にpointer-events:auto;
たったこれだけ。
後は親や兄、子要素それぞれイベントを設定します。
デモのCSSを関係箇所のみ抜粋したものはこちら。
デモCSS抜粋
//親 .parent { pointer-events : none; transition : all 0.5s ease-in-out; ... } //兄 .parent p { transition : all 0.5s ease-in-out; ... } //子 .child { pointer-events : auto; transition : all 0.3s ease-in-out; ... } //親のイベント[a] .parent:hover { ... } //兄のイベント[b] .parent:hover p { ... } //子のイベント .child:hover { ... }
親要素のイベントトリガー領域を子要素でマスクする感覚に近い?
通常は親要素にホバーイベントなどを設定してしまうと、親要素全体がトリガー領域になってしまいます。
しかし今回のテクニックの場合、親のイベントのトリガー領域は子要素(pointer-events:auto;を指定した要素)の範囲に限定されます。
その様子が親要素のトリガー領域を子要素でマスクしているようにも感じました。
また、あたかも子要素で発生させたイベントに見せつつ、子以外のイベント(上記抜粋内[a][b])は親(pointer-events:none;を指定した要素)からのセレクタ指定で各々設定するところもポイントかもしれないです。
pointer-events:auto;は明示的に指定する必要あり
pointer-eventsの初期値はautoですが、このプロパティは継承するので今回の場合は明示的にautoを指定する必要があります。
クロスブラウザほぼ対応
このテクニックの良い所はJSに依存しないのに加えて、各ブラウザの比較的新しいバージョンであれば概ね使用が可能なところかと思います。
[番外編]ホバーイベントなどで子孫・兄弟(弟)要素のスタイルを操作する方法
今まで見てきたのはトリガー要素の親や兄要素に対するスタイル操作ですが、トリガー要素の子要素をスタイル操作する場合はpointer-eventsテクニックは不要。
上述したデモCSS抜粋内の兄のイベント[b]がそれにあたります。
.parent:hover p {
ほにゃらら
}
この場合、「.parent p:hover」と書いてもうまくいきません。
あくまでホバーする対象は親の.parentなので、「ホバーした.parentの子孫要素であるp要素」をほにゃららする、という風に考えるとわかりやすいかもです。
弟要素等のスタイル操作
仮にHTMLが
<div class="old"></div> <div class="young"></div> <div class="young"></div> <div class="young"></div>
だったとすれば、
直後の兄弟要素を指定
.old:hover + .young {
ほにゃらら
}
後に続く兄弟要素全てを指定
.old:hover ~ .young {
ほにゃらら
}
などとなり、基本的にはCSSの結合子が使えます。