CSSのhas()疑似クラス関数の使い方


昨今のWebサイトは内容が変化するような動的なサイトが多く、CSSで装飾してWebサイト制作していく中、対象の要素を持っているかどうかで、スタイルを変更していきたいこともあります。

なかなかCSSのみでは実装できない部分ですが、今後はCSSの:has()疑似クラスを使うことで、HTML構造や内容の変化で、スタイルを調整していくことができるようになるでしょう。

:has()疑似クラスは、指定した要素を持つ要素を指定する擬似クラスになります。

JavaScriptライブラリのjQueryなどでは、.has()メソッドが用意されており、指定したセレクタやDOM要素を持つ要素を取得して処理をしていくことができます。
要素を持っているかどうかも、jQueryなどで処理しなくても、今後はCSSで行えるかもしれません。

以下、Webブラウザのサポート状況になります。

Can I use(:has)
https://caniuse.com/?search=has()

2022年3月現在は、まだ開発段階ですので多くのWebブラウザで動作しませんが、Safariではバージョン Safari 15.4からmacOSとiOSでサポートされています。またSafariの新機能を試すことができるデバッグ用のWebブラウザ「Safari Technology Preview」で確認することができます。

なかなか便利そうな擬似クラス。
どのように使っていくのか、今のうちに覚えておくと良いでしょう。

:has()疑似クラスの利用


サンプルとして、同じようなパターンのコンテンツブロックを用意してみます。
まずはHTMLから。

HTML

<div class="box">
  <h2>Headline</h2>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>

<div class="box">
  <h2>Headline</h2>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>

<div class="box">
  <h2>Headline</h2>
  <p>text... text... text... text... text... text... </p>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>



最後のCSSクラス「box」のブロックだけ、p要素を含めて違いをつけてみました。
このp要素を持っているかどうかで、スタイルを変更してみます。

続いてCSSになります。
CSSクラス「box」の要素は、共通のスタイルとして装飾していきます。

CSS

* {
  margin: 0;
  padding: 0;
}

.box {
  border-bottom: 2px solid #eee;
  border-radius: 3px;
  max-width: 800px;
  margin: auto;
  padding: 20px;
  background: #ffd7d7;
}

ul {
  list-style: none;
  background: #ffbaba;
}

ul li {
  color: #333;
  padding: 0.5rem 1rem;
}

div:has(p) {
  background: #d7d7ff;
}

div:has(p) li {
  background: #babaff;
}

h2:has(+ p) {
  color: #00f;
}



divのコンテンツブロックにp要素を持っているかどうかを、「:has(p)」として:has()擬似クラスを使って指定し、背景色を変更しています。
また、p要素を子要素として持つ親要素のdivのli要素「:has(p) li」に対しても、背景色を変更。
他にも、h2の直後にp要素が隣接している「:has(+ p)」場合にも、隣接セレクタを使うなどして、これまでのCSSと同じようにセレクタを指定して、スタイルを効かせることができます。

CSSの:has()擬似クラスによるスタイルの適応



以下、:has()擬似クラスを使ったWebブラウザの動作です。
動画(3分)



まだ本格的にWebブラウザはサポートしておりませんが、今後1、2年でWebブラウザの開発が進み、CSSのみでスタイルを調整していけるようになることを期待しています。

まだまだJS頼みになるのかな。