Share on

CSS擬似クラス :has() でHTML/CSSスニペットを作る

CSS擬似クラス :has() でHTML/CSSスニペットを作る

今まで子要素の変化に対して親要素または祖先要素のスタイルを設定するためには、JavaScriptの設定が不可欠でした。しかし擬似クラス :has() の登場によりそれらは必要なくなりました。

:has()は、既存の擬似クラスやセレクタとも併用して使用できるため理解もしやすく、すぐに実装ができます。

今回は、擬似クラス :has() の使い方を、実用的な例をお見せしながら解説します。
実務で通じるHTML/CSSスニペットを作成していきましょう。

CSS擬似クラス :has() の便利なところ

:has() 特定の要素や条件を指定して親要素を取得し、スタイルを指定できます。

まずJavaScriptと比較して記述を見ていきましょう。
下記の方法で、id=”child”(子要素)からid=”parent”(親要素)を取得することができます。

【JavaScript】

  const child = document.getElementById("child");
  console.log(child.parentNode);

【CSS】

  #parent:has(#child) {}

子要素の変化に対して親要素のスタイルを変更する場合には、JavaScriptの記載に加えてCSSの記述も必要です。

classを取得するだけであれば単純な記載ですが、機能が複雑化していくと条件式が追加される場合もあります。 そのたびにJavaScriptとCSSを渡り歩くのは面倒ですし、メンテナンス性にかけます。
そのためスタイルの変化に対してCSSだけで完結できるのは、楽ですね。

さまざまな要素の取得

親要素の取得だけでなく、セレクタを使用して複雑な位置にある兄弟要素や隣接要素も取得できます。
さらにフォーム要素で多用する擬似クラス「:checked」の有無や、リストの個数の計算も可能です。
今までCSSで取得可能だった要素をそのまま条件として使用することができます。

:has() による実用的なHTML/CSSスニペット例

ここでは実用的なHTML/CSSスニペットをいくつかご紹介します。
取り上げるのはこちらです。

  • カードコンポーネント
  • フォームの変更
  • サイトカラーの変更
  • リンクの下線の有無を子要素で判断する

カードコンポーネント

カードのデザインは多岐にわたりますが、実装・運用面でつまづくのは以下のようなケースです。

  • 画像が設定されていない場合
  • リンク先がない場合
  • 異なるバリエーションのパーツが入る場合
  • カードの個数が増加した場合

これらを擬似クラス:hasで解決していきます。

カードコンポーネント

画像が設定されていない場合

  .card:not(:has(img)) {
      justify-content: flex-end; /* テキスト群を末尾に寄せる */
   }

補足:画像がない状態のカードを非表示にすることも出来ます。


リンク先がない場合

  .card:has(>a[href=""]) {
      pointer-events: none; /* クリック出来ないようにする */
  }

補足:aタグの有無によって矢印アイコン等のリンクのデザインの出し分けも可能です。


異なるバリエーションのパーツが入る場合

  .card:has(.card__button) {
      display: block;
      text-align: center;
  }

カードの個数が増加した場合

  .card__wrapper:has(.card:nth-child(2n)) .card{
    width: 50%;
  }
  .card__wrapper:has(.card:nth-child(4n)) .card{
    width: 25%;
  }

補足:グリッドレイアウトを使用すると親要素の指定だけで列の制御が可能です。

フォームの変更

項目がチェックされた時に表示させたいボタンや、変更したいデザインがある場合、これまではその都度、JavaScriptで親要素にclassを追加し変更を行ってきました。
同じことを擬似クラス :has() で実行することができます。


選択の有無によってリセットボタンを表示する

項目がcheckedされたときにリセットボタンを表示します。

選択の有無によってリセットボタンを表示する
  .btnReset{
    display: none;
  }
  .checkbox:has(input:checked) .btnReset{
    display: block;
  }

選択によって要素を表示または非表示にする

「other(その他)」を選んだら、解答欄を追加で出現させます。

選択によって要素を表示または非表示にする
  .form:has(option[value="renewal"]:checked) .renewalField {
    display: block;
  }
  .form .renewalField {
    display: none;
  }

サイトカラーの変更

サイトのテーマによって全体のカラーを変更できるようにしたいとき、CSS変数を使用して解決します。
テーマによってclass名のルールを予め決めておくと使い回しができるので便利です。

サイトカラーの変更
  :root{
    --color-1: black;
  }
  html:has(.typeRed){
    --color-1: red;
  }
  html:has(.typeBlue){
    --color-1: blue;
  }
  html:has(.typeRed) :is(header,footer){
    background-color: var(--color-1);
  }
  html:has(.typeBlue) :is(header,footer){
    background-color: var(--color-1);
  }

リンクの下線の有無を子要素で判断する

aタグ内にテキスト以外のHTML要素があるとき下線を表示しないようにしたい場合は、以下のように :has() を使用します。

リンクの下線の有無を子要素で判断する
  a { text-decoration: underline; }
  :is(a, button):has(*) {
    text-decoration: none;
  }

擬似クラス :has() を使用する時の注意点

:has() はFirefoxでは正式に対応していませんが、設定で有効にすることはできるため表示の確認ができます。
これは開発者用の操作となり標準装備されている機能ではありません。したがってモダンブラウザの対応が求められる案件には不向きな実装となります。(Firefox ver.115 時点)

おわりに

スタイルを変更する際、これまでは他の技術を経由してからの実装が常でした。idやclassの追加による表示の変更、styleをHTMLへの直接の記載など、見た目は正常でも管理が煩雑化していたのです。

しかし現在ではCSSのみで変更したい対象を捉えるだけでなく、HTMLの動作に合わせた実装を施すことが可能となりつつあります。変更するファイルが1つのため運用の面でも、とくに優れた技術になると思います。

WEB上での表現の幅が広がるだけでなく、もっと多くのデザインと実装方法が生まれてくるでしょう。
その時々の環境に合わせた最適な実装方法を常に考慮して対応を心がけていきたいです。

クーシーブログ編集部

この記事を書いた人

クーシーブログ編集部

1999年に設立したweb制作会社。「ラスクル」「SUUMO」「スタディサプリ」など様々なサービスの立ち上げを支援。10,000ページ以上の大規模サイトの制作・運用や、年間約600件以上のプロジェクトに従事。クーシーブログ編集部では、数々のプロジェクトを成功に導いたメンバーが、Web制作・Webサービスに関するノウハウやハウツーを発信中。

お問い合わせはこちらから

Web制作デザイン、丸ごとお任せ

お問い合わせする

Share on

お問い合わせはこちら

CATEGORY LIST