レンちゃんとペンタ

【CSS擬似クラスの:has()】つまり、子から親を探せるというコトです

【CSS擬似クラスの:has()】つまり、子から親を探せるというコトです

「div > p」などのように、親から子を特性するセレクタ用法は有名ですが、擬似クラスの:has()を使うと、その逆「子にp要素を持っているdiv」をセレクタにする事ができます。

この記事で分かること

  • 擬似クラス:has()の使い方とメリット

    Webデザインとブログで豊かに引きこもる。

    レンちゃんとペンタ

    Webデザインは器。ブログは中身。
    「レンちゃんとペンタ」では、2つのスキルを掛け合わせて、
    おウチで豊かに楽しく暮らす方法をご紹介しています。

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

    今回は、書籍リストのようなサンプルでお話します。

    • Illustratorの本
    • Photoshopの本
    • HTML / CSSの本売り切れ
    <ul>
      <li>Illustratorの本</li>
      <li>Photoshopの本</li>
      <li>HTML / CSSの本<span class="soldOut">売り切れ</span></li>
    </ul>
    

    うち、「売り切れ」のカラムだけスタイルを変えたいとします。
    :has()を使うと、次のように「span要素を持っているli要素」だけをセレクタにすることができちゃいます。

    /* spanを持っているli要素のスタイルだけを変える */
    li:has(span){
      opacity: .5;
    }
    
    • Illustratorの本
    • Photoshopの本
    • HTML / CSSの本売り切れ

    idやクラスも指定可能

    :has()の括弧の中には、タグ名だけでなく、idやクラスも入れられます。
    先ほどのCSSであれば、こんな表記も定義できるということです。

    /* .soldOut要素を持っているli要素のスタイルだけを変える */
    li:has(.soldOut){
      opacity: .5;
    }
    

    子要素でも孫要素でもOK

    条件となる要素が何階層下にあっても大丈夫です。
    これでも、

    <!-- liから見ると、.soldOutは子要素 -->
    <li>
      <span class="soldOut">売り切れ</span>
    </li>
    

    これでも、

    <!-- liから見ると、.soldOutは孫要素 -->
    <li>
      <p><span class="soldOut">売り切れ</span></p>
    </li>
    

    ちゃんと追っかけてくれます。

    :has()を活用すればJavaScript要らず

    ここからは実用例をご紹介。
    サンプルはメール一覧みたいイメージですが、:has()を使って次のような機能を実装しています。

    ・チェックを入れた行の背景色を変える
    ・一つでもチェックが入っている場合、「選択したメールを削除する」のリンクを表示
    ・プルダウンでヘッダーの色を変えられるようにする

    受信メール一覧
    選択したメールを削除する
    <table>
      <thead>
        <tr>
          <th>受信メール一覧
            <select>
              <option value="blue">Blue</option>
              <option value="pink">Pink</option>
            </select>
          </th>
         </tr>
      </thead>
      <tbody>
        <tr>
          <td><input type="checkbox">メール1</td>
        </tr>
        <tr>
          <td><input type="checkbox">メール2</td>
        </tr>
        <tr>
          <td><input type="checkbox">メール3</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td><a href="#">選択したメールを削除する</a></td>
        </tr>
      </tfoot>
    </table>
    
    /* カラムに下ボーダーをつける */
    table tbody td{
      border-bottom: 1px solid #EEE; 
    }
    
    /* ヘッダーのデフォルトの背景色はブルー */
    table th{
      color: #FFF;
      background: #42699F;
      display: flex;
      justify-content: space-between;
    }
    
    /* デフォルトでは「選択したメールを削除する」は非表示 */
    table tfoot td:last-child{
      display: none;
      text-align: right;
    }
    

    チェックを入れた行の背景色を変える

    例えばこんなのを実装すると、チェックボックスにチェックを入れたカラムの背景色が変わります。

    /* チェックを入れたtd要素の背景色を変更 */
    td:has(input:checked) {
      background-color: #EEE;
    }
    

    一つでもチェックが入っている場合、「選択したメールを削除する」のボタンを表示

    さらにこんなのを加えると、チェックが一つでも入っている場合のみ、削除用のメニューが出るようになります。

    /* 一つでもチェックが入っている場合は、「選択したメールを削除する」を表示(noneからblockに) */
    table:has(input:checked) tfoot td{
      display: block;
    }
    

    プルダウンでヘッダーの色を変えられるようにする

    最後にこんなのも。

    /* プルダウンでpinkを選択時に背景色を変更 */
    th:has(option[value="pink"]:checked){
      background-color:#E32A75;
    }
    

    プルダウンの選択によって、カラーが変わるようになります。便利!

    まとめ

    親から子を特定するセレクタはよく用いられますが、

    /* divを親に持つp要素を指定する */
    div > p{ }
    

    has:()を使うと、その逆ができるようになるという事ですね。

    /* pを子孫に持つdiv要素を指定する */
    div:has(p){ }
    

    役割としてはそれだけなんですが、最後にご紹介した通り、JavaScriptや各種プログラムがないと実装できなかった仕組みをCSSだけで作れるようになるので、アイデア次第では相当お役立ちの用法になるはずです。

    1. Home
    2. 【CSS擬似クラスの:has()】つまり、子から親を探せるというコトです

    Related Posts