やあ。現場でCSSと格闘している君たちへ。
フロントエンドの現場では、ボタンや入力フォームのUIを触っていると、「子要素にフォーカスが当たった瞬間に、親要素全体をハイライトさせたい」という欲求に駆られることがよくあるよね。そんな時、昔ならJavaScriptで`focusin`イベントを拾ってクラスを付け替える……なんて泥臭いことをしていたはずだ。
だが、今は令和だ。CSSの `:focus-within` があれば、その苦労は過去のものになる。今回は、この強力な「親の状態を制御する」ための擬似クラスについて、現場視点で深掘りしていこう。
—
:focus-within の本質:DOMの「伝播」を味方につける
`:focus-within` を一言で言えば、「自分自身、もしくは自分の配下のどこかにフォーカスがあるとき、自分自身にスタイルを当てる」ためのセレクタだ。
ブラウザの裏側では、フォーカスイベント(`focus`)のバブリングを利用して、フォーカス状態がDOMツリーを駆け上がっていく様子を監視している。この擬似クラスは、その監視の結果として「今、お前の配下で誰かがアクティブだぞ」という情報をCSSエンジンが検知し、スタイルを適用する仕組みなんだ。
これの何が素晴らしいかって、JavaScriptを一切汚さずに「コンテナ単位」でのUX改善ができる点に尽きる。
—
実践:現場で即座に使える「フォームグループ」のハイライト
よくある「ログインフォーム」のデザインで考えてみよう。入力欄(input)にフォーカスが当たったとき、その親である `.form-group` 全体を強調したい……というケースだ。
/ フォーム全体を囲むコンテナ /
.form-group {
padding: 16px;
border: 2px solid #ccc;
border-radius: 8px;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
/
- ここが肝!
- .form-group 内の input や button にフォーカスが当たると、
- .form-group 自体のスタイルが切り替わる
/
.form-group:focus-within {
border-color: #007bff;
box-shadow: 0 0 8px rgba(0, 123, 255, 0.25);
}
/ おまけ:フォーカス中であることをラベルにも伝える /
.form-group:focus-within label {
color: #007bff;
font-weight: bold;
}
このコードの何が良いか分かるかな? もし中に `select` や `textarea` が増えても、コードを一行も書き足す必要がない。`.form-group` の中にフォーカス可能な要素がある限り、このスタイルは自動的に適用されるんだ。これが「宣言的UI」の強みだよ。
—
なぜ「JSでの制御」を避けるべきなのか
後輩から「これJSでやった方が制御しやすいんじゃないですか?」と聞かれることがある。確かにJSなら「フォーカスが外れたらクラスを外す」という挙動を細かく制御できる。
だが、JSでやるということは:
1. メインスレッドを無駄に消費する: スクロール中や重い処理が走っている時にJSが動くと、UIがカクつく原因になる。
2. 保守性の低下: DOM構造が変わるたびにJSのセレクタ修正が必要になる。
3. 初期表示のチラつき: JSが読み込まれるまでのタイムラグで、意図しないスタイルの不整合が生まれる。
CSSで完結できることは、CSSで完結させる。これがフロントエンドの鉄則だ。`:focus-within` は、ブラウザのレンダリングエンジンに直接計算を任せるから、パフォーマンスの面でも圧倒的に有利なんだよ。
—
現場で気をつけるべき「落とし穴」
便利な `:focus-within` だが、一つだけ注意点がある。それは「フォーカスが当たっている要素そのものが何であるか」を区別しにくいという点だ。
例えば、フォームの中に「削除ボタン」と「入力欄」が混在しているとする。どちらにフォーカスが当たっても親要素が青く光ってしまうと、ユーザーは「今どこに入力中なのか」を誤認する可能性がある。
そんな時は、CSSの `is()` 疑似クラスと組み合わせると、より精度の高い制御ができるようになる。
/ 「入力欄」にフォーカスがある時だけ親を強調したい場合 /
.form-group:focus-within:has(input:focus) {
border-color: #007bff;
}
※ `:has()` はモダンブラウザでフルサポートされているから、今すぐ現場のプロジェクトで使っていい。`:focus-within` と `:has()` を組み合わせれば、CSSだけで「かなり高度なロジック」が記述できるはずだ。
—
まとめ:CSSアーキテクトからのアドバイス
`:focus-within` は、単なる「便利な機能」じゃない。UIの複雑さを「DOM構造の階層」へと押し込めるための、非常に強力なツールだ。
コードを書くときは常に「これはJSに頼るべきか、CSSの宣言に任せるべきか」を自問自答してほしい。`:focus-within` を使いこなすことは、無駄なJSを削除し、ブラウザの力を最大限に引き出す、まさに「プロの仕事」だと言える。
さあ、エディタを開いて、君の書いているフォームを一段階洗練させてみようじゃないか。分からないことがあれば、またいつでも聞いてくれ。

コメント