【テクニカル・上級編】 :target 擬似クラス – CSS実践ガイド

`:target` 擬似クラスを使いこなす:ブラウザのネイティブ挙動を味方につけた「脱JavaScript」のアーキテクチャ

フロントエンド界隈では、ReactやVueといった強力なフレームワークが台頭し、状態管理といえばグローバルストアかコンテキストが当たり前になった。だが、我々のような「ブラウザの深淵」を覗くアーキテクトにとって、CSSが本来持っているネイティブな状態管理能力を無視するのは、あまりに勿体ない。

今回は、あえて `:target` 擬似クラスという、古くからあるが極めて強力なツールに焦点を当てる。これを単なる「ページ内リンクのハイライト」と捉えているなら、それは宝の持ち腐れだ。

—

`:target` が持つアーキテクチャ上の本質

`:target` は、現在のURLのフラグメント識別子(`#`以降の文字列)が、要素の `id` と一致した瞬間に発火する。これは単なるスタイル適用ではない。ブラウザのヒストリーAPIと密結合した、「ステートマシン」そのものなのだ。

JavaScriptでモーダルを開閉する際、`useState`を更新し、仮想DOMを再描画させ、再レンダリングのライフサイクルを回す……。これに対し、`:target` を使えば、ブラウザのエンジンが直接DOMツリーを走査し、該当要素のスタイルを再計算する。この「オーバーヘッドの差」は、特に低スペックデバイスや、複雑なDOM構造を持つエンタープライズアプリケーションにおいて顕著な差となって現れる。

実装:メモリ効率を最大化するアプローチ

単に要素を表示・非表示にするだけなら `display: none / block` で十分だが、パフォーマンスを極限まで追求するなら `visibility` や `opacity`、あるいは `contain` プロパティとの併用を検討すべきだ。

/

  • 描画パフォーマンスを最適化する戦略的アプローチ
  • ‘content-visibility: auto’ を併用することで、
  • 非ターゲット時のレンダリング負荷を最小化する

/
.modal-container {
display: flex;
visibility: hidden;
opacity: 0;
transition: opacity 0.3s ease;

/ レンダリングのコストを抑制 /
content-visibility: auto;
}

/ フラグメントが一致した瞬間にのみ描画コストを発生させる /
.modal-container:target {
visibility: visible;
opacity: 1;
}

現場で陥る「非同期競合」とバグ回避の極意

`:target` には、JavaScriptとの混在による「状態の不整合」という落とし穴がある。例えば、SPAのルーターが管理するURLの変更と、`:target` によるモーダルの開閉がバッティングした場合だ。

最も危険なのは、`history.pushState` を発行した直後に `:target` が反応し、意図しないスクロール挙動が発生することである。これに対する我々の回答は、「CSS側でスクロールを制御し、JS側でイベントをキャンセルする」という多層的な防御だ。

/

  • 意図せぬページジャンプを阻止するCSS
  • ターゲット要素に対して、スクロール挙動を無効化する

/
.modal-overlay {
scroll-behavior: auto;
/ targetが当たった瞬間に勝手にブラウザがスクロールするのを防ぐ /
anchor-name: none;
}

パフォーマンス最適化の観点から:再計算コストの削減

CSSセレクタの評価回数は、ブラウザのメインスレッドを占有する要因の一つだ。`:target` を使用する際は、なるべくセレクタを具体化し、ブラウザエンジンが要素を特定する際の計算量を減らす必要がある。

  • 避けるべき記述: ` :target { … }` (全要素をスキャンさせるのは禁忌)
  • 推奨する記述: `.modal:target { … }` (特定のクラスを持つID一致要素に絞る)

また、`position: fixed` や `absolute` を使用するモーダルであれば、`will-change: transform;` を付与することで、GPUアクセラレーションを有効に活用できる。ただし、これはメモリを消費するため、本当に必要なコンポーネントに限定して適用するのがプロの流儀だ。

結論:なぜ今、`:target` なのか

我々が目指すべきは、「JSが書けないからCSSでやる」といった妥協の産物ではない。「JSが介入する必要がない場所には、可能な限り介入させない」という、堅牢なアーキテクチャの構築だ。

`:target` は、ブラウザがネイティブで提供する強力な「状態保持機能」である。これを使えば、JSのバンドルサイズを削り、メモリ使用量を抑え、たとえネットワークが遮断されても、URLさえあればモーダルが開くという、極めてレジリエンスの高いアプリケーションが実現できる。

次のスプリントでは、あなたのアプリケーションにある「ただのフラグ管理のためのJS」を、一度 `:target` に置き換えてみてほしい。そのとき、ブラウザ本来の軽やかさが戻ってくるはずだ。それが、フロントエンド・スペシャリストとしての一歩先のアプローチである。

コメント

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