ヘッダーナビをホバーした時に、子メニューが表示されるようにしたけど動き変。
マウスアウトして非表示にした後、要素があった箇所にマウスを移動させるとまた表示される!
なんで??opacity: 0;
、visibility: hidden;
にしているのに……。
ホバー時に表示させる子メニューですが、transition
が入っていると完全に非表示になっておらず、意図せずマウスホバーして要素が再表示されることがあります。
子リストはデフォルトでpointer-event: none;
、ホバー時だけpointer-event: auto;
にすることで解消されます。
そもそもどういう問題?
問題のサンプルをCodePenで用意しました。
ホバーすると子要素が表示されます。一度マウスアウトしてから、子要素があった箇所にマウスを戻すと子要素が表示されてしまいます。
- マウスホバーすると、子要素が表示
- マウスアウトすると、子要素は非表示
- 子要素があった箇所にマウスを戻すと、また子要素が表示される。
【原因】transitionの影響で、要素が完全に非表示になっていないことで起きます
See the Pen 極端な例 by shimpei (@shimpei) on CodePen.
子要素にtransition
を入れている場合に起きる問題です。transition
を0
にすると起きないですが、ふわっと表示・非表示させたいですよね。
解決方法を解説していきますね。
完成形のイメージ
最終的な完成形です。
マウスアウトした後に、子リストの箇所にマウスホバーしても子リストは表示されません。
いい感じですね。
See the Pen header nav hover by shimpei (@shimpei) on CodePen.
CodePenのサンプルは、大好きなchocolatさんカラーにしてみました。
解決方法
原因はtransition
でした。transition
で設定した時間内は要素は表示されています(見かけは透明でも)。
要素が完全に消えていない状態だと要素をホバーできるので、意図せず要素が表示されてしまいました。
これを解消するには、pointer-event: none;
にして要素をホバーできなくすれば良いです。
CSS
- 子リストはデフォルトで、
pointer-event: none;
- 親リストをホバーした時だけ、子リストを
pointer-event: auto;
にする
// 親のリスト
ul.h-navlist01 {
> li {
position: relative;
&:hover {
// 親リストをホバーしたら、子リストを表示
ul.h-navlist01-child {
// ホバーした時だけポインターイベント有効
pointer-events: auto;
opacity: 1;
visibility: visible;
}
}
}
}
// 子のリスト
ul.h-navlist01-child {
// ポインターイベント無効(デフォルト)
pointer-events: none;
position: absolute;
opacity: 0;
visibility: hidden;
}
その他|実装時に役立つ小技
親リストと、子リストに隙間があるときは、子リストにmargin-top
を入れます。
本題と別ですが実装時に役立つ小技を紹介します。
親リストと、子リストの間に隙間があるとマウスホバーが外れてしまいます。
マウスホバーが外れると、子リストは表示されません。そういった場合は隙間分だけ子リストにmargin-top
を入れます。
margin-top
でマウスホバーが外れる隙間を埋めます。
まとめ|子リストのポインターイベントを無効にする。
- 子リストのポインターイベントは、デフォルトで無効にする(
pointer-event: none;
) - 親リストをホバーしたときだけ、子リストのポインターイベントを有効にする(
pointer-events: auto;
)
最後までありがとうございました!