こんにちは。wdtチームの山本です。
今回は、最近知って実際に試してみたCSSセレクタ :has() について紹介します。
最近のCSSはかなり進化していて、「これCSSだけでできるんだ」と感じることが増えてきました。その中でも :has() は、実務でも使いどころが多く便利だと感じたので、今回記事にまとめてみました。
:has()とは?
:has() は CSS の疑似クラスです。
これまでCSSだけでは難しかった、子要素の状態によって親要素の見た目を変えることができます。
例えば、
- 子要素に hover したら親カードの背景色を変える
- checkbox が checked のときラベル全体のデザインを変える
といったことが可能です。
これまではJavaScriptやjQueryでクラスを付与して対応することが多かったですが、:has() を使うことでCSSだけで完結できるケースが増えます。
使用時の注意点
便利な :has() ですが、使う際に注意したい点もあります。
:has() はDOMの状態を参照してスタイルを判定するため、使い方によってはブラウザの再計算コストが増えることがあります。
そのため、
- 深い階層で多用する
- 複雑な条件を重ねる
といった使い方は避け、必要な箇所に絞って使うのが良さそうです。
また、 :has() は「子要素から親要素へ」影響を与える書き方になるため、HTML構造に依存しやすいという面もあります。
制作途中でマークアップ構造が変わった際に「なぜスタイルが当たらないんだろう?」となりやすいので、保守性の面では少し注意が必要です。
対応ブラウザについて
:has() は比較的新しいCSS機能ですが、現在は主要ブラウザで対応が進んでいます。
- Chrome
- Safari
- Firefox
- Edge
主要ブラウザではほぼ利用可能なため、現在のWeb制作では採用しやすくなっています。
※ただし、古いブラウザでは事前確認が必要です。
以前までの処理
これまでは、子要素の hover をきっかけに親要素の見た目を変えたい場合、JavaScriptやjQueryを使うことが多かったです。
例えば以下のような形です。
HTML
<div class="card">
<a href="#" class="btn">hover me</a>
</div>CSS
.card {
padding: 32px;
border: 1px solid #ddd;
transition: .3s;
text-align: center;
width: 50%;
margin: 2em auto;
}
.btn:hover{
color: #ffffff;
transition: .3s;
}
.card.is-hover {
background: #1fc9f3;
}jQuery
$(function(){
$('.btn').hover(function(){
$(this).parent('.card').toggleClass('is-hover');
});
});このように、
hover検知
↓
class追加・削除
↓
CSS適用
という流れで制御していました。
:has()では
これが :has() を使うと、CSSだけで書けます。
HTML
<div class="card">
<a href="#" class="btn">hover me</a>
</div>CSS
.card {
padding: 32px;
border: 1px solid #ddd;
transition: .3s;
text-align: center;
width: 50%;
margin: 2em auto;
}
.btn:hover{
color: #ffffff;
transition: .3s;
}
.card:has(.btn:hover) {
background: #1fc9f3;
color: #f7f33b;
}かなりシンプルになりました。
まとめ
今回 :has() を触ってみて感じたのは、「今までJavaScriptで対応していたものをCSSに寄せられる便利なセレクタ」ということです。
もちろん、
- DOM構造への依存
- パフォーマンス面への配慮
など注意点もあります。
ただ、
- カードhover
- ナビゲーション
- フォームUI
などではかなり使いやすく、実装もシンプルになります。
すべてを :has() に置き換えるというより、「CSSだけでできそうならまず試してみる」くらいの使い方がちょうど良さそうです。
今後も実務の中で、活用できる場面があれば積極的に使っていきたいと思います。


