「:target-within」で、ちょっと賢いCSSの世界へようこそ! – 隠れた「あの要素」を見つけ出す魔法
こんにちは!CSSの世界へようこそ。フロントエンドの魔術師、なんて呼ばれたりもする僕ですが、最初はみんなと同じように、コードとにらめっこしながら「うーん、どうしてこうなるんだ?」って悩んでた時代もありました。
CSSって、見た目を整える魔法みたいで楽しいですよね。でも、時々「もうちょっと、こうだったらなぁ…」って思うこと、ありませんか?特に、ある要素が「選ばれたとき」に、その親っこまでおしゃれさせたい、なんてシチュエーション。
例えば、お店で欲しいものを見つけて、それを手に取ったとき。その「手に取った」っていうアクションで、お店の入り口の看板までキラキラさせたい!…なんて、ちょっと大げさすぎますかね?(笑)
でも、Webサイトでも似たようなことはよくあるんです。
- メニューを開いたとき、そのメニューを囲んでる枠線をもっと太くしたい!
- 「あとで買う」リストに入れた商品が、そのリスト全体の背景色を変えてほしい!
こんな時、今までのCSSだと、ちょっと面倒だったり、JavaScriptを使わないと難しかったりすることがありました。
でも、今日ご紹介する `:target-within`(ターゲット・ウィズイン) という、ちょっぴり新しいCSSの仲間がいるおかげで、そんな願いがもっと簡単に叶うようになるんです!
:target-within って、一体どんな魔法?
まずは、この `:target-within` の名前を分解してみましょう。
- `:target`:これは、URLの末尾についてる `#` の後にくる、特定の「ターゲット」になった要素のこと。例えば、`index.html#section1` ってURLなら、`id=”section1″` の要素がターゲットになります。
- `within`:これは「~の中」とか「~以内」っていう意味。
つまり、`:target-within` は、
「ターゲットになった要素自身、もしくは、そのターゲット要素の『中(子孫)』にいる要素がターゲットになったときに、その親要素を選んでね!」
っていう、とっても親切なセレクタなんです。
具体的に、どういうこと? 身近な例で考えてみよう!
想像してみてください。あなたは大きなショッピングモールに来ています。
1. モール全体 (親要素)
2. 服屋さん (子要素)
3. その服屋さんの中にある、お目当てのTシャツ (ターゲット要素)
ここで、あなたが「このTシャツ、すごくいいね!」って手に取ったとします。
すると、`:target-within` は、こう考えてくれるんです。
「おや? Tシャツが選ばれたぞ。Tシャツは服屋さんの『中』にいるな。じゃあ、その服屋さん(親要素)をちょっと目立たせてあげよう!」
…と、こんなイメージです。
もっと分かりやすく言うと、
- URLに `#about` ってついたら、`id=”about”` の要素がターゲットになります。
- もし、その `id=”about”` の要素の中に、さらに `id=”team”` っていう要素があって、URLが `#team` になったら、これも `id=”about”` の要素の「中」でターゲットになっていることになります。
この `:target-within` は、どっちの場合でも、`id=”about”` の要素にスタイルを適用できる、っていう優れものなんです。
今までの `:target` との違いは?
「あれ? `:target` っていうのもあったよね?」って思ったあなた、鋭い!
`:target` は、あくまで「ターゲットになった要素そのもの」にしかスタイルを適用できませんでした。
例えば、
セクションタイトル
ここにコンテンツが入ります。
セクション1
セクション1のコンテンツです。
セクション2
セクション2のコンテンツです。
サブセクション
サブセクションのコンテンツです。
このコードで、もし `:target` を使って、セクションの親(例えば `body` とか、もし親となる `div` があればそれ)にスタイルを適用しようとしても、URLが `#section1` になったときに、`:target` は `section1` 要素自身にしか反応しません。
でも、`:target-within` ならどうでしょう?
もし、`section2` の中にさらに `div class=”sub-section”` があって、URLが `#sub-section` になったとしても、`:target-within` は `sub-section` の親である `section2` にも反応してくれるんです!
この「中」まで見てくれるところが、`:target-within` のすごいところなんです。
いよいよ実践! `:target-within` を使ってみよう!
では、実際にコードを書いて、`:target-within` の効果を見てみましょう。
今回は、メニューのようなものをイメージして、クリックしたらそのメニューの親要素に目印(例えば背景色)をつけたり、もっと見やすくしたりする例をやってみます。
例1:クリックしたメニューの「枠」を強調する
:target-within でメニューを賢く装飾しよう
各メニューの「項目」リンクをクリックしてみてください。
クリックした項目が属するメニュー(親要素)の枠線や背景が変化するのがわかりますか?
ヒント:
URLの末尾を `#item1-1` や `#item2-2` のように変えて、直接ページにアクセスしても同じ効果が得られます。
URLが `#item1-1` になると、`id=”menu1″` の `div` の中にターゲット要素 (`item1-1` がもし存在すれば) があるとみなされ、`.menu-container:target-within` のスタイルが適用されます。
このコードをブラウザで開いて、「メニュー1」の中の「項目 1-1」や「項目 1-2」のリンクをクリックしてみてください。
どうでしょう? クリックしたリンクが属する `.menu-container` の枠線が緑色に変わって、背景も少し明るくなりましたよね!
これは、`:target-within` が、「`.menu-container` の中に、URLで指定されたターゲット要素(例えば `#item1-1`)があるよ!」と判断して、`.menu-container` にスタイルを適用してくれているからです。
もし、HTMLの構造を少し変えて、`#item1-1` のような要素を実際に作って、URLを `#item1-1` に直接変更しても、同じように `.menu-container:target-within` が発動します。
:target-within が活躍する「ちょっとした」場面
この `:target-within` 、どんな時に便利か、もう少し具体的に考えてみましょう。
- アコーディオンメニューやタブメニュー:
開いているセクションや、選択されているタブの親ブロック全体を強調したいときに。
- インタラクティブな地図や図:
地図上の特定のエリアをクリックしたら、そのエリアを囲む大きな領域(例えば、そのエリアが含まれる「都道府県」の枠)をハイライトしたいとき。
- フォームのバリデーション:
入力エラーがあったフィールドの親コンテナ全体に、エラー表示の背景色をつけたいとき。
これらはほんの一例ですが、`:target-within` を使うことで、これまでJavaScriptでゴリゴリ書かなければ難しかった表現が、CSSだけでシンプルに実現できるようになるんです。
つまずきやすいポイント&フォローアップ
さて、ここまで読んで「なるほど!」って思ってくれたなら嬉しいです。でも、CSSって、やっぱりちょっとしたことで「あれ?」ってなったりしますよね。
:target-within を使う上で、ちょっと気をつけておきたいことがあります。
1. ターゲット要素が実際にHTMLに存在する必要がある?
URLに `#some-id` って書いても、HTMLの中に `id=”some-id”` の要素がなければ、`:target-within` は反応しません。あくまで、実際に存在する要素がターゲットになった場合に発動します。
でも、今回のように、リンクの `href` を `#item1-1` としておいて、実際に `id=”item1-1″` の要素がなくても、そのリンクがクリックされた(=URLが `#item1-1` になった)という事実だけで、親の `:target-within` は発動します。これは、URLのハッシュ部分だけで状態管理をしたい場合に便利なんですよ。
2. ブラウザの対応状況は?
`:target-within` は比較的新しいセレクタなので、古いブラウザ(特にInternet Explorerなど)では使えません。
ですが、最近のモダンブラウザ(Chrome, Firefox, Safari, Edgeなど)では問題なく使えます。もし古いブラウザへの対応が必要な場合は、JavaScriptでの代替手段を検討する必要があります。
「じゃあ、使えないじゃん!」って思うかもしれませんが、大丈夫。Webサイトのほとんどは、最新のブラウザで見られることがほとんどですし、もし本当に古いブラウザ対応が必要なケースなら、その時はJavaScriptの出番です。でも、それ以外なら、CSSだけでこんなにカッコいいことができるんです!
3. `:target` との使い分け
「結局、`:target` と `:target-within`、どっちを使えばいいの?」って迷うかもしれませんね。
- `:target`: ターゲットになった要素「そのもの」だけにスタイルを適用したい場合。
- `:target-within`: ターゲットになった要素「自身、またはその子孫」がターゲットになった場合に、その「親」や「祖父母」にスタイルを適用したい場合。
今回の例のように、メニューの親ブロックを強調したいなら `:target-within` がぴったりです。
まとめ:CSSの可能性は、まだまだ広がる!
`:target-within` は、URLの `#` を使った状態管理とCSSを連携させる、とってもパワフルなセレクタです。これまでJavaScriptの領域だったような、インタラクティブな表現を、CSSだけで、しかもシンプルに実現できる可能性を秘めています。
今回ご紹介した例は、ほんの入口に過ぎません。ぜひ、この `:target-within` を使って、あなたのWebサイトに新しい「賢さ」と「楽しさ」を加えてみてください。
「あの要素が選ばれたら、こっちの親もこうしたいな…」
そんなあなたのアイデアが、`:target-within` によって、きっと形になりますよ!
CSSの世界は、まだまだ奥深く、そして驚きに満ちています。これからも一緒に、この楽しい世界を探求していきましょう!

コメント