CSSの:has()を使うと、相対セレクターが関連する内容や要素に一致する場合に、その基準要素を選択できます。たとえばarticle:has(img)は画像を含むarticleに一致します。「親セレクター」と呼ばれることがありますが、定義上は子孫だけでなく基準要素から見た相対関係を表せます。意図しない範囲に広がらないよう、条件と対象を明確にします。

.card:has(> img)が直接のimg子要素を持つカードに一致し、wrapper内にimgがあるカードには一致しない比較

1. 相対セレクターの基準点

:has()の引数は相対セレクターのリストです。調べる要素が基準となり、そこからの関係を記述します。section:has(> h2)なら直下の子に見出しを持つsectionを探します。:has(.error)のように子孫関係を限定しない条件より範囲が明確です。マッチするのは基準にしたsectionであり、条件に一致した子孫そのものではありません。

引数にはカンマ区切りで複数のセレクターを指定でき、いずれかの条件を満たすと一致します。複雑な論理を追加する前に、どの祖先やコンテナーに状態を反映すべきか決めます。関係を限定すると意図を読み取りやすくなり、コンポーネントのマークアップ変更による予想外の一致も抑えられます。

2. フォームやカードでの例

フォームではlabel:has(input:invalid)のように、関連する入力の状態に応じてラベルを選べます。カードにメディアがある場合だけ表示を変えたり、選択済みチェックボックスがあるコンテナーに状態スタイルを適用したりできます。DOMを書き換えたりJavaScriptで状態クラスを同期したりする重複を減らせる場合があります。ただし入力の妥当性はHTMLフォーム規則に従い、見た目の変更は説明テキストやアクセシブルなフィードバックの代わりにはなりません。

コンポーネントのルートで:has()を使うと、内部要素の条件を外側のレイアウト選択につなげられます。たとえばcard:has(.thumbnail)はサムネイルがあるカードの表示を選べます。入れ子の別コンポーネントまで偶然条件に含めないよう、必要ならクラスや直下子の結合子で範囲を限定します。

3. 詳細度と実ページでの動作を確認

:has()の詳細度は引数リスト内で最も詳細なセレクターに基づきます。そのため複雑な条件を加えると、見た目より強い規則になることがあります。cascade layerや低詳細度の設計を使っていても、開発者ツールで最終的に勝つ宣言を確認してください。:where()との組み合わせで引数の詳細度を制御できる場合がありますが、対象規則とレイヤー順も合わせて調べます。

構文だけで一定の性能コストが決まるわけではありません。非常に広い文書範囲に複雑な条件を適用すると、保守やデバッグが難しくなります。代表ページで対象要素数やDOM変更後の一致結果を確認し、必要なコンポーネントに範囲を絞ります。対象ブラウザーのすべてが:has()に対応しない場合は、@supports selector(:has(*))などの機能クエリーで代替スタイルを整理できます。

4. 専門家の視点:適用場所を決める

W3C Selectors仕様は:has()を関係疑似クラスとして定義し、相対セレクターの評価方法を規定します。MDNの開発者向け案内はフォーム状態や内容の有無に関する実用例と、詳細度・対応状況の考慮点を示します。これはDOMを任意に逆走するスクリプト機能ではなく、宣言的なCSSセレクター照合です。視覚的なスタイルだけでよいのか、別の意味状態や動作が必要なのかも区別します。

導入時は基準要素、相対関係、引数の詳細度、対応ブラウザーを明らかにします。代表的な入れ子構造でテストし、アクセシビリティに必要な状態説明が残ることも確認します。範囲を絞った関係セレクターは重複した状態クラスを減らせますが、あらゆるDOM関係を一つの複雑な規則で表す必要はありません。

参考資料