👻

[CSS] 子要素がないときに親要素を消す際は:has()を利用すると良い

2024/02/13に公開

:has()の登場以前

:has()が利用できるようになり、CSSでの表現力は飛躍的に上がっている(:has()は最近のモダンブラウザならどれでも利用できるような状態である)。

https://caniuse.com/css-has

Chrome Edge Safari Firefox Safari on iOS
105 105 15.4 121 15.4

:has()が使えない環境では、子要素がないときに親要素を消したいような要件の際、以下のように制限があった。

data属性の値をバックエンドで判定する

<div class="parent" data-is-empty="true">
   <div></div>
</div>
.parent[data-is-empty="true"] {
  display: none;
}

:emptyで判定する

:empty擬似クラスを使用して、子要素(テキスト・ノードを含む)を持たないかどうかを判定する。ただし、parentクラスの要素に何かがノードが含まれている場合は:empty判定にならないため、アプリケーションの仕様によっては使えないケースもある。

<div class="parent"></div>
.parent:empty {
  display: none;
}

:has()を利用しない場合の課題

先述の例だと特に:has()を利用しなくとも解決策はあるが、以下のような状況のときにCSSだけでは判定が難しくなる。

<div class="parent">
  <h2 class="heading">見出し</h2>
  <div class="child">
    <!-- ここが動的に変わる -->
  </div>
</div>

.childの中身が空の場合、見出し(.heading)も合わせて非表示にしたいケースだ。

.parentをまるごと消しておかないと、.parentにデザイン上の余白などがあった場合に全体的な整合性が取れなくなる。その場合(.parentを消す)場合、先述のように判定用にdata属性の付与(バックエンドの力)が必要になる。

頑張った例

頑張った例

フロントエンドだけで頑張らないといけない場合も世の中にはある。ただ、これはかなり無理があるし、これではすぐに破綻する。

<div class="parent">
  <div class="child"></div>
  <h2 class="heading">見出し</h2>
</div>
.parent {
  display: flex;
  flex-direction: column-reverse;
}

.parent .child:empty,
.parent .child:empty + .heading {
  display: none;
}

:has()の登場後

.childが空の場合は:empty擬似クラスとの組み合わせで空に出来るし、.parentごと非表示に出来る。

<div class="parent">
  <h2 class="heading">見出し</h2>
  <div class="child">
    <!-- ここが動的に変わる -->
  </div>
</div>
.parent:has(.child:empty) {
  display: none;
}

さらに以下のように.moreのように固定で存在するような要素が含まれる場合でも、このCSSで変わらず要素をまるごと非表示にすることが出来る。

<div class="parent">
  <h2 class="heading">見出し</h2>
  <div class="child">
    <!-- ここが動的に変わる -->
  </div>
  <a class="more" href="/more">もっと見る</a>
</div>
株式会社ZOZO

Discussion