こんにちは!フロントエンド・スペシャリストの私です。
日々のWeb制作、本当にお疲れ様です。CSSを書き始めた頃って、「あれ、これってどうやってスタイルを当てればいいんだっけ?」と手が止まる瞬間が何度もありますよね。特に、「子どもの状態に合わせて、親の見た目を変えたい!」と思ったことはありませんか?
昔のCSSは、「親から子へ」一方通行にしかスタイルが流れない仕組みでした。だから、子どもの要素に合わせて親をデザインしようとすると、「しょうがない、JavaScriptの出番か……」と頭を抱えるのがお決まりのパターンだったんです。
でも、安心してください。もうそんな昔の苦労をする必要はありません。
現代のCSSには、救世主である `:has()` 疑似クラス(通称:親セレクタ)がいます。
今回は、この `:has()` の使い方を、身近な例え話と一緒に優しく紐解いていきましょう。肩の力を抜いて、一緒に見ていきましょうね!
—
1. `:has()` ってなんだろう? お店の「看板」で例えてみる
まずは難解な専門用語を置いておいて、イメージから膨らませてみましょう。
街を歩いているとき、「中に犬が入れるカフェ」を探しているとします。そのお店の入り口に「ペット同伴OK」というステッカーが貼ってあるのを見たとき、あなたはそのカフェ全体(=親)を「あ、ここはペットと一緒に過ごせる場所だな(=スタイルを適用)」と認識しますよね。
これをCSSで考えてみましょう。
- 子ども(中身):お店の中にいる「ペット」や「特定のアイテム」
- 親(建物・エリア):カフェの店舗そのもの
従来のCSSは「外側から内側」しか見られませんでした。しかし、`:has()` を使うと、「おいおい、お前の中身にアレが入っているなら、お前自身の見た目を変えてやるぜ!」と、内側を覗き見して外側の親をスタイリングできるようになるんです。
これが、「親セレクタ」と呼ばれる所以です。すごそうでしょう?
—
2. つまずきがちなポイント:「何を指定するの?」
`:has()` を使い始めるとき、誰もが一度は「括弧の中に何を書けばいいんだっけ…?」とフリーズします。大丈夫、私も最初は頭がこんがらがりました。
書き方の基本ルールはこうです。
/ 親要素 :has( 条件となる子孫・兄弟要素 ) { スタイル } /
ポイントは、「括弧の中には、見つけ出したい目印(セレクタ)を書く」ということ。
百聞は一見にしかず。具体的なコードを見ていきましょう!
—
3. 実践!よくあるシチュエーションで使ってみよう
ここでは、Web制作の現場で「あ、これやりたかったやつ!」となる代表的な2つの例をご紹介します。そのままコピペして、お手元のエディタで試してみてくださいね。
パターンA:チェックボックスがONになったら、カード全体をハイライトしたい!
お問い合わせフォームなどで、「チェックを入れたら、その項目の背景色がフワッと変わる」というリッチなUIを作りたいとき、ありませんか?
昔ならJavaScriptで「`change` イベントを拾ってクラスを付け外しして……」と書いていましたが、`:has()` ならCSSだけで完結します。
/ カードの基本スタイル /
.card {
display: flex;
align-items: center;
gap: 12px;
padding: 16px;
border: 2px solid #ddd;
border-radius: 8px;
transition: all 0.3s ease; / パッと変わるのではなく、優しく変化させます /
cursor: pointer;
}
/ ★ここがポイント!
「内部の .real-checkbox が :checked(チェック状態)になっている」を持つ .card を選ぶ /
.card:has(.real-checkbox:checked) {
background-color: #e6f4fe; / 優しい青色に変化 /
border-color: #1a73e8; / 枠線も目立たせる /
}
どうでしょう? たったこれだけで、チェックを入れた瞬間にカード全体がフワッと青く光るようなインタラクションが作れます。JSを1行も書いていないなんて、なんだか魔法みたいですよね。
—
パターンB:画像がない記事カードは、レイアウトをスッキリさせたい!
ブログやメディアサイトを作るとき、「画像がある記事」と「テキストだけの短いお知らせ記事」が混ざることはよくありますよね。画像がないのに、画像用のスペースがポッカリ空いてしまってカッコ悪い……なんて悩んだことはありませんか?
`:has()` を使えば、「画像を持っているかどうか」で親要素のデザインを切り替えられます。
ちょっとしたつぶやき
今日は良い天気ですね。
/ 記事カードの基本スタイル /
.post-card {
display: grid;
grid-template-columns: 1fr; / デフォルトはテキストだけの1カラム構成 /
gap: 16px;
padding: 20px;
border: 1px solid #eee;
}
/ ★ここがポイント!
「内部に を持っている」 .post-card のときだけ、グリッドの列を2つに分ける /
.post-card:has(img) {
grid-template-columns: 200px 1fr; / 左に画像、右にテキストのレイアウトに変化 /
}
.post-card img {
width: 100%;
height: auto;
border-radius: 4px;
}
これによって、HTMLの構造をわざわざ変えたり、クラス名(`has-image`みたいな)をJavaScriptで動的に付与したりしなくても、CSSだけで「画像があるときは左右分割、ないときは1カラム」という美しいレスポンシブな出し分けができるようになります。最高ですね!
—
4. チーフアーキテクトからのアドバイスと、そっと伝えたい注意点
ここまで読んで、「`:has()` って最強じゃん! 全部これで作ろう!」と思ったそこのあなた。その探求心、とても素敵です。
ただ、実務の現場に立つプロとして、一つだけお伝えしておきたいことがあります。
それは、「便利だからといって、あらゆる場所で複雑な `:has()` を使いすぎないこと」です。
`:has()` はブラウザが内部で「この要素の中に、あの要素はあるか……?」と一生懸命チェック(再計算)をしています。あまりにも深すぎる階層や、巨大なリストの中で複雑な条件を書きすぎると、ページのスクロールがカクついたり、パフォーマンスに影響が出たりする可能性があります。(※最近のブラウザは非常に優秀ですが、意識しておいて損はありません)
「ここぞ!」というコンポーネントの切り替えや、フォームのインタラクションなど、「JavaScriptを書くほどではないけれど、CSSだけだと今まで泣く泣く諦めていた痒いところ」にそっと使ってあげるのが、一番スマートで美しい使い方です。
—
おわりに
CSSの `:has()` 疑似クラス、いかがでしたか?
最初は「親を選ぶなんて難しそう…」と感じたかもしれませんが、身の回りの仕組みや例えに置き換えてみると、ぐっと身近に感じられたのではないでしょうか。
フロントエンドの世界は日進月歩で進化しています。「昔はできなかったあんなことやこんなことが、今のCSSならこんなにシンプルに書けるんだ!」という発見を楽しむことが、スキルアップの一番の近道です。
今日学んだコードを、ぜひあなたのエディタやCodepenなどで実際に動かしてみてくださいね。
あなたのWeb制作ライフが、もっと楽しく、もっと自由になりますように。それではまた、次の現場でお会いしましょう!

コメント