👌

CSSカスケード ~詳細度~

に公開

前回の続き

詳細度とは

詳細度とは、どのスタイルが優先されるかを決める仕組みのこと。

CSSのスタイル適用の優先順位は「オリジンと重要度」「カスケードレイヤー」「詳細度」「スコープ近接性」「記述順」となるが、詳細度はこの中で3番目の優先順位となる。

つまり、「オリジンと重要度」「カスケードレイヤー」が共に同じ場合、詳細度によってどのスタイルが優先されるかが決まる。

MDNのドキュメント

詳細度の表し方

詳細度は「A-B-C」という3つの数値で表される。A, B, Cの意味は以下の通り。

  • A: IDセレクター( #id )の数
  • B: クラス(.class)、属性([attr])、疑似クラス(:hoverなど)の数
  • C: 要素型(divなど)と疑似要素(::beforeなど)の数

[type="password"],          /* 0-1-0 */
input:focus,                /* 0-1-1 */
:root #myApp input:required /* 1-2-1 */
{
  color: blue;
}

詳細度の比較

以下のcssがあるとする。

#myElement {
  color: green; /* 1-0-0 */
}
.bodyClass .sectionClass .parentClass [id="myElement"] {
  color: yellow; /* 0-4-0 */
}

そして以下のhtmlがあるとする

<div class="bodyClass">
  <div class="sectionClass">
    <div class="parentClass">
      <input id="myElement">
    </div>
  </div>
</div>

このとき <input id="myElement">はどのスタイルが適用されるか。
この場合、詳細度が高いのは#myElementのため文字色はgreenになる。
詳細度は左の数字から比較する。

細かな仕様

:is() :not() :has()

これら3つは詳細度の計算においては擬似クラスとはみなされない。

代わりに引数のセレクターが詳細度の計算に使われる。
:is()の場合、引数のなかではもっとも詳細なものを採用する。

div:is(.test) p {
  /* 0-1-2 */
  /* IDは0 クラスが1つ(.test) 要素が2つ(div, p) */
  /* :is()は擬似クラスだが詳細度に含まれない */
}

div:is(.test, #fakeId) p {
  /* 1-0-2 */
  /* IDが1つ(#fakeId) クラスが0 要素が2つ(div, p) */
  /* :is()の引数は#fakeIdが採用される */
}

CSS入れ子に対してもis()と同じ計算になる。

p,
#fakeId {
  span {
    /* 1-0-1 */
    /* 「:is(p, #fakeId) span」と書いたときと同じ */
  }
}

where()

引数の中のセレクターは詳細度に影響を与えない

:where(#defaultTheme) a {
  /* 0-0-1 */
  /* 要素が1(a)
}

@scope

詳細度に影響を与えない。
:scopeは擬似クラスとして詳細度に関わるので混同しないように注意。

@scope (.light-theme) {
  :scope {
    /* 0-1-0 */
    /* 擬似クラスが1つ(:scope) */
  }
  p {
    /* 0-0-1 */
    /* 要素が1つ(p) */
  }
}
GitHubで編集を提案

Discussion