要約

  • W3Cの2018年2月草案には名前の決まっていない「重みゼロ」の擬似クラスがあり、同年11月の草案で:where()と名付けられた。
  • :where()の中身は要素の判定に使われるが、詳細度には加算されない。外側のセレクターは通常どおり数えるため、共通ルールの強さを作者が調節できる。

発端はa:not(:hover)だ。ホバーしていないリンクの下線を消す。ところがメニューを作る人はnav aで下線を付け直したい。後から書けば勝てそうだが、CSSは行数より詳細度を先に見る。前者には擬似クラスがあり、後者は要素セレクターが二つ。メニューの下線は戻らない。ここでクラスを足し、さらにクラスを足し、しまいには!importantに手を伸ばす。たった一本の線に、妙に物々しい装備が集まってくる。

2018年11月21日のW3C草案は、この例をそのまま取り上げている。提案はa:where(:not(:hover))。ホバーしていないリンクを選ぶ条件は変わらない。だが:where()内の条件は詳細度を増やさず、外側のaだけが残る。二つの要素を数えるnav aがメニュー内で勝つ。共通ルールを書いた人が一歩引いたおかげで、局所的な用途を書いた人が普通のセレクターで仕事を済ませられる。

名前が決まる前から、その席は用意されていた。2018年2月2日の草案は、:matches()に似た重みゼロの擬似クラスを記録し、名称を未定としていた。11月の草案が:where()という名前を載せ、CSS Working Groupの公表記事もその変更を紹介した。要素を探す能力の追加というより、探し当てた後にどれほど強く主張するかを作者が選べるようにした進展だ。

セレクターには二つの役目がある。ルールを適用する相手を見つけることと、競合する宣言の順位に影響を与えることだ。:where()は前者を残し、括弧の中の後者をゼロにする。2022年5月7日の草案の例では、.qux:where(em, #foo#bar#baz)の詳細度は(0,1,0)。括弧内のIDは照合に使えても、重みは持ち込めない。外側の.quxだけがクラス一つ分を数える。選択範囲を決める精度と、勝負の声量は別々に設定できる。

この性質は、共通の部品を配る側に効く。基本のリンクやフォームを正確に選びたい一方、各ページでは別の表情にしたいことがある。共通ルールが最初から高い詳細度を抱えれば、利用側は毎回もっと長いセレクターを用意する。:where()を選べば、共通の見た目は出発点になり、地域ごとの変更やコンポーネント固有の判断がCSSの通常の仕組みで通る。ブラウザーは計算を担当し、どのルールを控えめにするかは作者が決める。

2022年11月11日の草案には、関数型セレクターで使う寛容なリストの構文規則もある。無効な項目を除き、有効な項目を残すという扱いだ。これは機能を増やす際の実務的な余地を与えるが、何でも書けば通るという免状ではない。W3Cの公開履歴に残る2018年から2022年の草案を通じ、中心にあるのは変わらない。共通のCSSが正しい相手を見つけても、その後のすべての相談に勝つ必要はない。