:has()疑似クラスの概要
みなさん、CSSの:has()疑似クラスについて追えてますか?
出回っている印象で言えば、子要素を条件に親要素を選択ですが、これは正確な表現ではありません。
より正確に表現するならば、セレクタを条件に要素を選択する機能です。
より正確に表現したほうが、分かりにくくなりましたね。
実際の例を見てみましょう。
<body>
<p>はじめまして</p>
<p>はじめまして、<span>こんにちは</span></p>
</body>
/* spanを含むpを選択 */
p:has(span) {
color: red;
}
/* 直後にpが隣接する場合に選択(つまり直前に隣接するpを選択) */
p:has(+p) {
color: blue;
}
指定した子要素の親要素を選択することは、これまでにできませんでした。
また、指定した要素の直前の要素を選択することもできませんでした。
すごくないですか?
僕はシンプルに興奮しています。
これを利用することによって、この例以外にも、今までできなかったことができるようになるはずです。
この記事では、:has()疑似クラスを用いて、こんなこともできるのではないか、という実験結果をまとめてみます。
CSS :has()疑似クラスはもう使える?
目新しい機能ではありますが、つい最近のアップデート(Chroe v105)によって、Chromeでは:has()疑似クラスが使えるようになりました。
まだ、すべてのブラウザで利用できるわけではないですが、現時点(2022年9月)では、Safari(mobile/pc)とChrome(pc)で利用できるようです。また、polyfill(JS)によってサポートされていないブラウザも問題なく動作させることができるようです。
今までできなかったけど、できるようになった選択手段
サンプルhtml
この記事で扱うサンプルは、以下のURLで確認・編集できます。
https://jsbin.com/fuvexejoco/1/edit?html,css,output
<p>para1</p>
<p>para2</p>
<ul class="list1">
<li>1</li>
<li>2</li>
</ul>
<ul class="list2">
<li>1</li>
<li>2</li>
</ul>
<ul class="list3">
<li>1</li>
<li>2</li>
</ul>
<select>
<option value="1" selected>1</option>
<option value="2">2</option>
</select>
以前の兄弟要素を選択
これまでも、指定要素以降の要素を選択することはできましたが、:hasを使うことで、以前の要素も選択できるようになりました。
/* ul以前のpを選択(以降にulを持つpを選択) */
p:has(~ ul) {
color: red;
}
直前の要素を選択
同様に、直前の要素も選択できます。
/* ulの直前に隣接するpを選択(直後にulが隣接するpを選択) */
p:has(+ ul) {
color: red;
}
n個以上の子を持つ要素を選択
/* .list2が2個以上のliを持つ場合に選択される */
.list1:has(li:nth-of-type(2)){
background-color: red;
}
子要素がn個未満の時に選択
/* .list2が3未満のliを持つ場合に選択される */
.list2:not(:has(li:nth-of-type(3))){
background-color: blue;
}
任意の数の子要素を持つ親要素を選択
つまり、n個以上n個未満というand検索ですね。
/* .list3が2以上3未満のliを持つ場合に選択される(つまり2つのliを持つ場合) */
.list3:has(li:nth-of-type(2)):not(:has(li:nth-of-type(3))){
background-color: yellow;
}
formの値によって先祖要素の変数を操作する
:root {
--bg-color: transparent;
}
p {
background-color: var(--bg-color);
}
/* selectの値として2が選択された場合に、htmlの変数を変更する */
html:has(option[value="2"]:checked) {
--bg-color: #ccc;
}
まとめ
いかがでしたでしょうか。
新しい機能(可能性)に触れるということは、興奮を憶えるものです。
ここで紹介した例は、実用的なものではありませんでしたが、次の機会(思いついたら)には実用例を紹介できればと思います。
特に要素数で選択する例は、カラム数によってレイアウトを変更するような場面で使えそうです。
その他、こんな方法もあるよ!というご意見などありましたら、どしどしお寄せください。
お待ちしております。