【実務・中級編】 フォーカス内擬似クラス :focus-within – CSS実践ガイド

やあ。現場で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を削除し、ブラウザの力を最大限に引き出す、まさに「プロの仕事」だと言える。

さあ、エディタを開いて、君の書いているフォームを一段階洗練させてみようじゃないか。分からないことがあれば、またいつでも聞いてくれ。

コメント

タイトルとURLをコピーしました