シェアする

【CSS】リストにhoverしたときにhoverしていない要素のスタイルも変更する方法【コピペOK】

シェアする

ことばでうまく説明できないので、まずは実際に動作してるのを見てください。

See the Pen ZEGQggj by yinouet (@yinouet) on CodePen.

HTMLの構造としてはemmet記法でいうとul>(li>a)*5になっています。

リストされたうちの一つにhoverすると、hoverしてない兄弟要素のスタイルも変わる、というやつです。

ナビゲーション用のメニューリストなんかにいいんじゃないでしょうか。

セレクタが複雑なので解説

仕組みはサンプルのコード見てもらえばだいたいわかると思いますが、SCSSを使っているので分かりづらいかもしれません。

コンパイル後のCSSで解説していきます。

まずHTMLはこちら。MindBEMdingに則ってクラスを付けています。

<ul class="list">
  <li class="list__item"><a href="#" class="list__link">MENU 1</a></li>
  <li class="list__item"><a href="#" class="list__link">MENU 2</a></li>
  <li class="list__item"><a href="#" class="list__link">MENU 3</a></li>
  <li class="list__item"><a href="#" class="list__link">MENU 4</a></li>
  <li class="list__item"><a href="#" class="list__link">MENU 5</a></li>
</ul>

で、CSSはこちら。

/* ul要素 */
.list {
  list-style: none;
  width: 20rem;
}

/* li要素 */
.list__item {
  background-color: #eee;
}
.list__item:hover {
  background-color: #000;
}

/* a要素 */
.list__link {
  display: block;
  width: 100%;
  height: 100%;
  padding: 1rem 2rem;
  text-decoration: none;
  color: #666;
}
.list__link:hover {
  color: #fff;
}

/* ここがポイント */
.list:hover .list__item:not(:hover) {
  background-color: #666;
}
.list:hover .list__item:not(:hover) > .list__link {
  color: #ccc;
}

この動きを実現しているのは最後2つのセレクタです、これらが何を指定しているのか見ていきましょう。

  • .list:hoverul要素がhoverされたとき
  • その子孫の.list__itemのうち
  • :hoverされていない( :not(:hover) )もの

および

  • その直接子要素の.list__link

を指定しています。

兄弟要素がhoverされている=親要素がhoverされているので、最初に親がhoverされているとき、というのが条件になります。

floatとか使って親要素の高さが0になっていると使えないので、そういう場合はちゃんとclearfixなりして親要素の高さを確保しておきましょう。

スタイルを当てたいのは子要素なのに一旦親要素に戻らないと指定できないので、ちょっとすぐには思いつきませんよね。

ちなみに。

hoverされていない兄弟要素ということで、次のように兄弟セレクタ ~ を使いたくなりますが、

.list__item:hover ~ .list__item:not(:hover)

これだとhoverされている要素より後ろの兄弟要素にしか適用されません。(実はこの挙動は初めて知りました。~セレクタ使ったことなかった)

まとめというか感想

MinbBEMdingの命名規則を使うとあまり子孫セレクタとか子セレクタを使うことってないと思っていましたが、このように使うこともできるのですね。

条件をひとつひとつ解きほぐしていくと、セレクタひとつでかなり複雑な指定もできることがわかりました。CSSは奥が深いですね。