IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

CSS3 のカスケーディングについてのおさらい

いつも忘れて、毎回どうだったっけって確認するのがめんどいのでまとめておきます。

仕様

参照する仕様は CSS3 とします。(ワーキングドラフトなので、この内容は変わる可能性があります)
CSS3 の仕様は以下から探してください
site:http://www.w3.org/TR/css3 - Google Search

カスケーディングとは

カスケーディングに関する言葉の意味は以下に書いてあります。

CSS allows several style sheets to influence the rendering of a document, and the process of combining these style sheets is called “cascading”.

http://www.w3.org/TR/css3-cascade/#abstract

超意訳すると

CSS では一つの HTML *1に対して複数のスタイルシートを使えます。そして、複数のスタイルシートを結合するプロセスのことを「カスケーディング」と呼びます。

ということです。
もっと簡単に言うと

  • 要素の見た目って複数の link 要素とか style 要素とか style 属性でいっぱい宣言するよね!
    • するする!
  • 宣言が被ったときに、どの宣言を適用するかを決めないといけないよね!
    • うんうん!
  • その宣言選択方法のことを「カスケーディング」っていうよ!
    • ひゃー!

ということです。

実際のカスケーディングを解説

カスケーディングの手順は以下に書いてあります。

The purpose of cascading is to find one winning declaration among the set of declarations that apply for a given element/property combination.
User agents must sort declarations according to the following criteria, in order of importance:

  1. Weight. In CSS3, the weight of a declaration is based on the origin of the declaration and its marked level of importance. See a separate section below for how to compute the weight. The declaration with the highest weight wins.
  2. Specificity. The Selectors module [SELECT] describes how to compute the specificity. The declaration with the highest specificity wins.
  3. Order of appearance. The last declaration wins. Rules in imported style sheets are considered to be before any rules in the style sheet itself. Rules in two imported style sheets are considered to be in the same order as the @import rules themselves.

The sorting process continues until one winning declaration is found.

http://www.w3.org/TR/css3-cascade/#cascading

超意訳すると

カスケーディングは、与えられた宣言の中から「勝つ宣言」を見つけることです。
すべての宣言を以下の順で、勝敗を決めていきます。

  1. 「weight(優先度)」の高い宣言が勝ちです。
  2. 「weight(優先度)」が同じものは、「specificity(詳細度)」の高い宣言が勝ちです。
  3. 「weight(優先度)」と「specificity(詳細度)」が同じものは、最後に宣言された宣言が勝ちです。(@import の場合は @import された CSS は @import した CSS より先にあるということになります、そして、 @import された CSS が複数ある場合は、 @import された順に宣言されているという風になります。)

ということです。
もっと簡単にいうと

  • この要素には width に関する宣言がいっぱい定義されているなあ。
    • 困ったね!
  • じゃあ、一番 weight(優先度)が高い宣言を適用するよ
    • でも、weight(優先度)が同じ宣言が三つもあるよ
  • じゃあ、その中で一番 specificity(詳細度)が高い宣言を適用するよ
    • でも、weight(優先度)も specificity(詳細度)も同じ宣言が二つあるよ
  • じゃあ、後に出てきたほうの宣言を適用するよ
    • ひゃー!

ということです。
(ちなみに、ショートハンドな宣言がある場合は、複数の宣言がそのルールセットに宣言されていると思えばいいです。)

weight(優先度)とは何か

めんどくなってきたので、仕様へのリンクはやめます。
優先度とは、その宣言が含まれるスタイルシートが誰によって与えられたかという情報と !important の有無によってきまります。
誰によって与えられたかは以下の三つのパターンがあります。

  • ウェブサイトによって与えられた
  • ウェブブラウザによって与えられた
  • ウェブブラウザのユーザによって与えられた(ユーザがブラウザの設定をカスタマイズしてたりする場合)

で、優先度が高い順に並べると

  • !important が含まれるユーザによって与えられた宣言
  • !important が含まれるウェブサイトによって与えられた宣言
  • !important が含まれないウェブサイトによって与えられた宣言
  • !important が含まれないユーザによって与えられた宣言
  • ウェブブラウザによって与えられた宣言

となります。

speficity(詳細度)とは何か

詳細度の高低は以下のように決まります。*2

  1. まず、ID セレクタ(#hogehoge, #fugafuga)の数が多いルールセットに含まれる宣言のほうが詳細度が高い
  2. 次に、ID セレクタ(#hogehoge, #fugafuga)の数が同じなら、クラスセレクタ(.hogehoge, .fugafuga)、属性セレクタ([title="hoge"], [class$="fuga"])、疑似クラスセレクタの合計数が多いルールセットに含まれる宣言のほうが詳細度が高い。
  3. 次に、IDセレクタの数と、クラスセレクタと属性セレクタと疑似クラスセレクタの合計数が同じなら、要素名セレクタ(div, ul, li)の数が多いルールセットに含まれる宣言のほうが詳細度が高い。
  4. 最後にこれらのすべてのセレクタ数が同じのなら、詳細度は同じ
  5. ちなみに、全称セレクタ(*)や疑似要素セレクタ(::before)は詳細度に影響を与えない。

style 属性

style 属性のことは、 CSS2.1 ではちゃんと詳細度として定義されているのですが、 CSS3 では何故か消されています。何故?
style 属性に書かれた宣言は実際の挙動としては、以下のような挙動をします。

  • ウェブサイトで宣言された宣言と style 属性で宣言された宣言を比べると style 属性の宣言が勝ちます
  • ウェブサイトで宣言された !important 宣言と style 属性で宣言された !important 付きの宣言を比べると style 属性の宣言が勝ちます

まとめ

もう忘れません

*1:CSS は HTML だけの仕様ではないので、本来は「文章(document)」とするべきだが、ここでは無駄に混乱させないために HTML と言い切った。

*2:僕が分かりやすいと思う書き方で書いてます。仕様と書き方が違いますが、同じことを示しています。