Interactive

CSS詳細度・カスケード可視化

「なぜそのスタイルが勝つのか」を、ブラウザと同じ手順で追えます。詳細度を数えるタブではセレクタを実際にパースして(a,b,c)をトークンごとに積み上げ、:where()が0に潰れることや:is()が引数の最大値を採ることも実際に適用します。カスケードの決着タブでは、宣言のオリジン・レイヤ・!importantを切り替えて、どの段で勝敗が決まったかを確認できます。

セレクタを入力すると、トークンごとに a(ID)・b(クラス/属性/擬似クラス)・c(要素型/擬似要素)のどこへ寄与するかを数え上げます。

aID

1

bクラス等

1

c要素型等

1

詳細度 = 1,1,1

トークンごとの内訳

#navID → a+1,0,0
(子孫)結合子+0,0,0
.itemクラス → b+0,1,0
(子孫)結合子+0,0,0
a要素型 → c+0,0,1

比較は a → b → c の辞書式です。bがどれだけ多くてもaが1つ多い相手には勝てません——#nav .item a(1,1,1)は.a.b.c.d.e.f.g.h.i.j(0,10,0)に勝ちます。:where()は引数に関わらず0,0,0に潰れ、:is()/:not()/:has()は引数の最大値を採ります。

セレクタは実際にパースして詳細度を積み上げ、カスケードも記事の比較順を実装した比較器で解決しています(ブラウザのCSSOMには問い合わせていません)。

ここが分かる

  • 詳細度の比較はa→b→cの辞書式で、重み付き合計ではない——#nav .item a(1,1,1)はクラス10個の.a.b…j(0,10,0)に勝つ。「classを増やせばいつか勝てる」は誤り。
  • :where()は引数が何であれ0,0,0に潰れるのに対し、:is()/:not()/:has()引数の最大値を採る——:where(.card)は0,0,0、:is(.card)は0,1,0と、上書きの敷居がまるで違う。
  • cascade layerは詳細度より上の段——appレイヤのa(0,0,1)がframeworkレイヤの.btn(0,1,0)に、詳細度を見るまでもなく勝つ様子を確認できる。
  • !importantオリジン順とレイヤ順の両方を反転させる——user !importantがauthor !importantに勝ち(アクセシビリティの砦)、レイヤでは先に宣言した方が最強・レイヤなしが最弱になる。実際に切り替えて順位が入れ替わるのを見られる。