グローバルナビゲーションへ

本文へ

フッターへ

お役立ち情報Blog



CSSでもifが使いたい!:has()擬似クラスを使ってCSSセレクタに条件分岐を書く方法

CSSでコーディングをしていると

  • 〇〇のときだけ××したい
  • □□のときは△△してほしい

といった「条件」によって「分岐」を必要とするセレクタを書く機会がたくさんあると思います。

CSSはシンプルで柔軟な言語ですので、セレクタを工夫することで大体の条件を満たすことができるのですが、シンプルがゆえに条件が混みあってくると、それに比例してセレクタも長く複雑なものになりがちです。

body.category001.device-pc .container.use-animation > article:nth-child(2) ul.active.use-border > li:not(.no-img) > a:hover::before { /*** ここにスタイル ***/ }

こんなセレクタを書かざるを得ないこと、たくさんありますよね?

CSSセレクタを簡潔に保つにはセレクタを必要最小限にするのが正攻法ですが、そのためには擬似クラスの理解は欠かせません。

本記事は2023年12月から全モダンブラウザで利用可能となった:has()擬似クラスの使い方について紹介します。覚えておいて損はないと思うので最後までお付き合いください。

:has()擬似クラスとは

:has()擬似クラスとはその名の通り「特定の状態の、子又は兄弟要素を持つ要素」を指定できるセレクタです。
言葉で説明するとちょっとわかりにくいですね…実際にCSSのコードを確認してみましょう。

<style>
.box {
  min-height: 200px;
  padding: 10px;
  border: 5px solid #dfdfdf;
}
.box > .img {
  width: 45%;
}
.box > .img img {
  max-width: 100%;
}
.box > .text {
  width: 100%;
}
.box:has(.img) {
  display: flex;
  justify-content: space-between;
}
.box:has(.img) > .text {
  width: 50%;
}
</style>

<div class="box">
  <div class="text">この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。</div>
  <div class="img">
    <img src="https://placehold.jp/1000x500.png" alt="">
  </div>
</div>

<div class="box">
  <div class="text">この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。</div>
</div>

このようにHTMLとCSSを用意すると、

このようにスタイルが適用されます。

ポイントはHTMLの構造やクラスのつけ方に変更を加えることなくレイアウトを変更しているという点です。上記例では「画像がある時はdisplay:flex;を適用して2カラムのレイアウトにする」という、よくあるレイアウトを実現しています。

:has()擬似クラスが利用できるまでは

<style>
.box.has-image {
  display: flex;
  justify-content: space-between;
}
.box.has-image > .text {
  width: 50%;
}
</style>

<div class="box has-image">
  <div class="text">この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。</div>
  <div class="img">
    <img src="https://placehold.jp/1000x500.png" alt="">
  </div>
</div>

<div class="box">
  <div class="text">この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。</div>
</div>

このように、親要素(div.box)にクラスを追加(div.has-image)するような形で対応していましたが、:has()擬似クラスがサポートされたことにより、今までのCSSセレクタでは実現できなかった「子要素の状態」という「条件」に対して、「親要素のスタイルを切り換える」という「分岐」を実装できるようになりました。

ブラウザの対応状況

※2024年3月7日時点

:has() CSS relational pseudo-class | Can I use… Support tables for HTML5, CSS3, etc

先述しましたが、2023年の12月に対応が遅れていたFireFoxでもサポートされたことにより、IEを除く全てのモダンブラウザで:has()擬似クラスを利用することが可能となりました。

FireFox以外のブラウザでは結構前からサポートされていたので、心待ちにしていたweb制作者も多いのではないでしょうか。

:has()擬似クラスの使い方

:has()擬似クラスは:hover:checkedのような他の擬似クラスと同じように、セレクタで指定したい要素に対して「:(コロン)」+「has()」の書式で記述しますが、「has()」の括弧の中にさらに子セレクタを指定することで、擬似クラスを指定したセレクタ(親セレクタ)の「条件」をさらに絞り込むことができます。(MySQLなどのリレーショナルデータベースを利用したことのある方は相関サブクエリをイメージしてもらえればOKです)

従来の擬似クラスと合わせて、基本的な使い方を見てみましょう。

<style>
/** :hover 擬似クラスの例 **/
.container a {
  color: black;
}
.container a:hover {
  color: royalblue;
}
/** :checked 擬似クラスの例 **/
.container input[type="checkbox"] + span {
  color: black;
}
.container input[type="checkbox"]:checked + span {
  color: red;
}
/** :has() 擬似クラスの例 **/
.container .parent:has(.child input[type="checkbox"]:checked) > p {
  color: red;
}
</style>

<div class="container">
  <p>▼▼▼:hover 擬似クラスの例</p>
  <div>
    <a href="#">マウスホバーでテキストの色が変わります</a>
  </div>
  <br>
  <br>
  <p>▼▼▼:checked 擬似クラスの例</p>
  <div>
    <input type="checkbox" name="n1" id="n1"><span>チェックが入ると色が変わります</span>
  </div>
  <br>
  <br>
  <p>▼▼▼:has() 擬似クラスの例</p>
  <div class="parent">
    <p>子要素のチェックでテキストの色が変わります</p>
    <div class="child">
      <input type="checkbox" name="n1" id="n1">親要素のテキストの色を変えるチェックボックスです
    </div>
  </div>
</div>

:hover:checkedはCSSコーディングしていれば日常的に使うものではないでしょうか。

それぞれ

  • マウスホバーでテキストの色が変わる
  • チェックの有無でテキストの色が変わる

と、要素の状態(条件)に応じて、スタイルが適用されます。
このように、自分自身の状態や、自分より前に出現する兄弟要素の状態による分岐はいままでも利用できましたが、:has()擬似クラスのサポートにより、3番目の例のように自身の子要素の状態による分岐も可能となりました。

.container .parent:has(.child input[type="checkbox"]:checked) > p {
  color: red;
}

:has()の括弧の中のセレクタが長くなると可読性が下がることは否めませんが、上記の例のようにユーザーアクションに応じて変更される子の状態を親に反映するにはJavaScriptの利用が必須でしたので、CSSだけで気軽に実装できるようになった恩恵は大きく感じます。(当社比)

お問い合わせフォームの簡易的なバリデーションなんかも作りやすくなるのでユーザビリティの向上にも一役買ってくれそうですね。

他にも、:not()擬似クラスとの組み合わせや、h1:has(+ h2)のように後続する要素を指定してのスタイルの適用など、様々な組み合わせで応用が効きますのでぜひ日々のコーディングに取り入れてみてください。(検索するといっぱいでてきて楽しいです)

さいごに

いかがでしたでしょうか。:has()擬似クラスを利用したCSSセレクタの使い方をご紹介しました。

お客様の要望やデザインの意図に応じて条件(セレクタ)が複雑になるのは仕方ない面もあるのですが、webサイトの修正や保守を考えるとできるだけシンプルで簡潔な記述にとどめたいと思うのがコーダーの心理ではないでしょうか。

CSSとブラウザの進歩の恩恵に預かって、より良いCSSコーディングができるように精進していきたい次第です。

この記事を書いた人

なかもと
なかもとソリューション事業部 マークアップエンジニア
企画・営業部を経て、システムエンジニア、マークアップエンジニアとしてweb サイト制作、webアプリケーション開発の上流から下流まで幅広く携わる。ユーザビリティ、アクセシビリティを意識したセマンティックなマークアップとより良いユーザー体験を追及して日々奔走中。三度の飯よりwebが好き。
この記事のカテゴリ

FOLLOW US

最新の情報をお届けします