これまでflex等で、親要素から見た子要素のCSSのだし分けはあったけれど、:has()疑似クラスが各ブラウザにサポートされたおかげで、実務面でいっきに楽になった気がする。
その中で、現場でつかえて画期的だと感じた:has()の使い方を紹介。
CSS :has()疑似クラスの基本的な使い方
has()の大きな特徴は子要素の要素の種類によって、親要素CSSの適用有無を設定できるようになったところだと思う。
基本的なCSSの:has()擬似クラスの使い方は、親要素が特定のパラメータを持つ子を保有しているかどうかを判定して、それに応じたCSSを適用する。
<div>
<p><img src=””><span>テキストRED</span></p>
<p><span>テキストBLUE</span></p>
</div>
上であればimg画像がある方のテキストを赤。
img画像がない方のテキストを青にしたいときは、
p:has(img) span{
color:red;
}
p span{
color:black;
}
という感じで、pタグの中にimg要素が含まれるかを判別して、テキストカラーを変えている

子要素を :has()疑似クラスを使って親を判定し、子にそれぞれCSSを出しわける
例)ヘッダーまわりのボタンをヘッダー幅100%に対して、孫要素(li)の数に応じて、liのボタン幅を変えたいとき。
(こんなとき、 ulやliにclassを追記できれば一瞬だけど、追加できないことは現場では日常茶飯事で……)
孫要素が2個のときは、2列(ボタン幅50%)
孫要素が3個のときは、3列(ボタン幅33%)
孫要素が4個のときは、4列(ボタン幅25%)
孫要素が5個のときは、5列(ボタン幅20%)
孫要素が6個のときは、3列2段(ボタン幅33%)
【前提条件】
修正条件として、classやタグなどのマークアップ追加修正は絶対不可。
nth-childなどで出来なくはないが、ヘッダー周りのボタンの個数(li)は不定期に数が減ったり増えたりする。
そのたびにCSS修正するのは手間がかかるし面倒。
どうせなら、ボタンの個数(li)が変わっても自動で幅が変わってくれる汎用性のあるCSSのにしておきたい。
こんなときhasなら対応できる
See the Pen has()を使って子要素から親要素を設定する by maco (@tmozou) on CodePen.
header{
width:600px;
}
ul {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
ul li{
list-style: none;
text-align:center;
margin-top:10px;
}
/* liが2個 */
.bottom ul:has(> :nth-child(2):last-child) li{
background-color:#fea78c;
width:49%;
}
/* liが3の倍数個 */
.bottom ul:has(> :nth-child(3n+3):last-child) li{
background-color:#80beaf;
width:33%;
}
/* liが4の倍数個 */
.bottom ul:has(> :nth-child(4n+4):last-child) li{
background-color:#90c4e9;
width:24%;
}
/* liが5の倍数個 */
.bottom ul:has(> :nth-child(5n+5):last-child) li{
background-color:#f583b4;
width:19%;
}CSSはどのliのときも「親要素に対して子要素(li)が〇個あるときの、子要素(li)」という感じで指定していった。
これならliの数の増減にもある程度耐えてくれる、はず。
