👻
[CSS] 子要素がないときに親要素を消す際は:has()を利用すると良い
:has()
の登場以前
:has()
が利用できるようになり、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>
Discussion