【実務・中級編】 :where() 擬似クラス – CSS実践ガイド

CSSの「詳細度」という呪縛を解く:`:where()`擬似クラスが現場にもたらす革命

フロントエンドの世界で長く戦っていると、必ずぶつかる壁がある。そう、「詳細度(Specificity)の地獄」だ。

「なぜかスタイルが当たらない」「`!important`が連鎖して収集がつかなくなっている」「サードパーティのライブラリが強すぎて自前のCSSが負ける」。これらはすべて、CSSの詳細度というルールが我々の意図を上回ってしまうことから生まれる悲劇だ。

そんな中、救世主のように現れたのが `:where()` 擬似クラスだ。こいつは単なる「セレクタのグループ化」ではない。CSS設計のパラダイムを根本から変えるポテンシャルを秘めている。今日は、この `:where()` の真価と、現場でどう使い倒すべきかを掘り下げていこう。

—

1. `:where()` とは何か:詳細度0という「免罪符」

まず、仕様を整理しよう。`:where()` は、カッコ内に渡したセレクタグループに対して、詳細度を一切持たせない(0にする)という特殊な機能だ。

/ 通常の書き方 /
.card .title { color: red; } / 詳細度: (0, 2, 0) /

/ :where() を使った書き方 /
:where(.card) .title { color: red; } / 詳細度: (0, 1, 0) /

見た目上は同じセレクタを指定しているように見えるが、`:where(.card)` の部分は詳細度としてカウントされない。これが意味するのは、「後からどんなに弱いセレクタで上書きしようとしても、抵抗ゼロでスタイルを差し替えられる」ということだ。

ブラウザはどう処理しているのか?

ブラウザのレンダリングエンジンは、CSSをパースする際、セレクタの詳細度を計算してツリー構造に反映させる。`:where()` に遭遇したとき、ブラウザは「ここの詳細度は無視せよ」というフラグを立てる。つまり、開発者体験(DX)としては「セレクタをグルーピングして記述量を減らす」ためのものだが、内部的には「スタイルの優先度を無効化する」という極めて強力な制約解除が行われているわけだ。

—

2. 現場でなぜ「:where()」を使うべきか

実務において、我々がCSSを書く目的は「複雑さを制御すること」にある。以下の2つのケースで `:where()` は無類の強さを発揮する。

ケースA:リセットCSSやベーススタイルの構築

ライブラリやコンポーネントライブラリを作っている場合、ユーザーのスタイルを邪魔したくないという設計思想があるはずだ。

/ 今までの辛い世界:詳細度が高すぎてユーザーが上書きできない /
.my-lib-button {
padding: 10px 20px;
background: blue;
}

/ 革命的な世界::where() で包むことで、詳細度を最小限に抑える /
:where(.my-lib-button) {
padding: 10px 20px;
background: blue;
}

こうしておけば、ユーザーが `button { background: red; }` と書くだけで、我々のライブラリのスタイルを綺麗に上書きできる。「あえて弱く作る」ことが、優れたUIライブラリの条件だ。

ケースB:CSSモジュールやユーティリティとの共存

Tailwind CSSのようなユーティリティファーストのフレームワークと、自前のコンポーネントCSSを混ぜて運用している現場は多いだろう。`:where()` を使えば、コンポーネント側の詳細度を「0」に固定できるため、ユーティリティクラスとの衝突を恐れる必要がなくなる。

—

3. 実践::where() を使った「防御的CSS」のサンプル

現場で即座に使える、モダンでメンテナンス性の高いコード例を置いておく。

/

  • リセットCSSの代わりや、コンポーネントの基本設計にて
  • :where() を使って詳細度を0に固定することで、
  • 後続のクラスやユーティリティによる上書きを容易にする

/

:where(h1, h2, h3, h4, h5, h6) {
margin-top: 0;
line-height: 1.2;
font-weight: 700;
}

/

  • リンクの初期スタイルもこれで安心
  • どこで誰がどんなセレクタを当てようが、簡単に打ち消せる

/
:where(a) {
text-decoration: none;
color: inherit;
}

/

  • 複数のセレクタをグルーピングしつつ詳細度をゼロにする
  • これでネスト地獄から解放される

/
:where(.card, .modal, .sidebar) .btn {
padding: 8px 16px;
border-radius: 4px;
}

—

4. 最後に:シニアからのアドバイス

「`:where()` は便利だが、思考停止して全てを包むな」と、あえて釘を刺しておきたい。

`:where()` は強力な「詳細度のリセットボタン」だ。しかし、CSSにおいて「意図的に詳細度を上げて、他のスタイルによる上書きを防ぐ」という戦略が必要な場面(例えば、絶対に崩れてはいけないレイアウトの基盤など)も存在する。

「上書きさせたい箇所は `:where()` で弱くし、意図的に守りたい箇所はあえて詳細度を持たせる」。この使い分けができるようになって初めて、CSSのアーキテクトとしての階段を一段登ったと言える。

CSSは、ブラウザが解釈するただの文字列ではない。君たちが書くCSSは、次にそのコードを触る誰か(半年後の君自身かもしれない)との対話だ。`:where()` を武器に、読みやすく、カスタマイズしやすく、そして何より「泥臭くない」スマートなCSSを構築してほしい。

何かあれば、またいつでも相談してくれ。コードは嘘をつかない。書けば書くほど、答えは見えてくるはずだ。

コメント

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