"カスケード"について
カスケード処理は、CSSの、おそらく最も重要な機構です。一読しておけば、CSSを作る上で一助となるでしょう。特に、複雑なCSSを書く時、何故うまくいかないのか分からない時には大いに参考になるでしょう。
継承
値は基本的に子要素、孫要素へと継承されていきます。SGMLでは、要素が入れ子されていく構造になっています。入れ子というのは、つまり
<h1>プログラマー 〜<em>文法を制する男</em>〜</h1>
上の例では、h1要素中にem要素が間借りしています。この状態を、「em要素がh1要素に入れ子になっている」と言います。
この文章に、以下のようなCSSを適用してみます。
h1 { font-size: 120% }
em { color: blue }
そうすると、h1要素 の文字の大きさは120%になります。em要素 は青色の文字で書かれます。
では、h1要素 に入れ子になっている em要素 の文字の大きさはどうなるでしょうか? h1要素 から値を引き継ぎ、h1要素 と同じ大きさになります。
これを継承と言います。
プロパティによって、値は継承したりしなかったりします。大抵は常識で考えて理解できる範囲ですが、扱いの難しいプロパティでは、なかなかそうはいきません。詳細は、各プロパティの表の、「継承」の欄をご覧ください。
'line-height' だけは継承のし方が特殊です。
[inherit]
レベル | 2- |
---|
レベル2では、値として[inherit]という、新しいキーワードが導入されました。これを用いると、通常継承されないプロパティや、祖先要素に応じて違う指定をしたいプロパティに、祖先の値を継承するようにさせる事が出来ます。
例えば、'border'は継承性を持ちませんが、[inherit]というキーワードを与えると、親要素から継承させることが出来ます。
<h2>マッドサイエンティスト <div>〜特殊ガラスを開発せよ〜</div></h2>
h2 { border: 3px solid purple }
h2 div { border: inherit ; margin: 10px }
このキーワードは単体で用います。何故なら、値が混在してしまうと、どの値としてこのキーワードが使われているのかが明確でなくなってしまうからです。
継承するのは、計算後の値です。つまり、各プロパティの表中「継承」の欄が「する」となっているプロパティでは、この値はあまり意味を成しません。
ただし、全く意味が無いわけではありません。スタイルの指定してある要素で、特殊な事情により元に戻したい時に有用です。
カスケード
では、本筋である"カスケード"の解説を始めます。
3種類のスタイルシート
CSSでは、立場的に、3つのスタイルシートがあります。
- UA固有のスタイルシート(デフォルトのスタイルシート)
- UAに何も手を加えていない状態で適用されるスタイルシートの事です。
- 文書作成者の作ったスタイルシート
- HTMLやXMLの文書にCSSの参照方法で示されている参照方法で結び付けたCSSの事です。
- ユーザのスタイルシート
- 見ている側が、UAに対して設定したスタイルシートの事です。
三者は、以下のような優先順位となっています。より右の宣言をより左の宣言が上書きします。
文書作成者の通常宣言>ユーザの通常宣言>デフォルトの通常宣言
@import規則 でインポートされた声明は、その出所と同じ立場として取り扱います。@import規則は@charset規則 の直後か、なければ最も最初に現れなければならなりません。ですので、@import でインポートされたスタイルシートはその出所のスタイルシートで上書きされていきます。
例としては、インポートするスタイルシート"culture.css"に
em { color: blue }
と指定し、インポート元のスタイルシートで
@import "culture.css";
em { color: red }
と指定すると、em要素 は赤色の文字で描かれます。要するに、@import でインポートした声明が @import規則 の代わりにそこに並んでいるものとして考えるわけです。
!important
レベル | - |
---|
ユーザのアクセシビリティを向上する為に作られた宣言です。アクセシビリティとは、アクセスし易さの事を指します。ユーザ側が、この宣言だけはどうしても適用したい時、譲れない時などに有用です。また作成者側でも、スタイルシートが複雑になって来た時に、ある宣言をほかの規則集合の一段上に置いておく意味で使用出来ます。
記述の仕方は、ごく簡単です。以下のように書きます。
p { text-indent: 1em !important }
[!]と[important]の間には空白類を入れても良い事になっています。ちなみに、宣言をグルーピングした場合には、以下のようになります。
body {
color: black !important;
background: white !important;
}
このように、ユーザが優先したい宣言の後ろに一つずつ付けます。
これは、最重要宣言と言って、これを付けると、宣言の優先順位が変わります。総合的に見ると、優先順位は以下のようになります。
ユーザ定義の最重要宣言>文書作成者の最重要宣言>文書作成者の通常宣言>ユーザの通常宣言>デフォルトの通常宣言
文書作成者はどう足掻いてもユーザ、つまり閲覧者にスタイルを強制する事は出来ないようになっていますね。
CSS1では、文書作成者の最重要宣言>ユーザ定義の最重要宣言で、アクセシビリティの観点から問題があったのですが、これが順序が逆になって、解決されました。
- CSS1とCSS2の相違点
- 最重要宣言の優先順位が変わりました。
詳細度
詳細度というのは、CSSのある要素に対する宣言同士がぶつかった時に解決策として用いる、計算によって導き出される値の事です。計算方法は至って簡単です。
- セレクタ内の一意属性を数え上げ、その数を「a」とします。
- ほかの属性及び疑似クラスを数え上げ、その数を「b」とします。
- 要素名を数え上げ、その数を「c」とします。
- 疑似要素は無視します。
で、出て来た値を a x 100 + b x 10 + c x 1 します。例を挙げると、以下のようになります。
* {} /* a=0 b=0 c=0 → 詳細度 = 0 */
li {} /* a=0 b=0 c=1 → 詳細度 = 1 */
ul li {} /* a=0 b=0 c=2 → 詳細度 = 2 */
ul ol+li {} /* a=0 b=0 c=3 → 詳細度 = 3 */
h1 + *[rel=up]{} /* a=0 b=1 c=1 → 詳細度 = 11 */
ul ol li.red {} /* a=0 b=1 c=3 → 詳細度 = 13 */
li.red.level {} /* a=0 b=2 c=1 → 詳細度 = 21 */
#x34y {} /* a=1 b=0 c=0 → 詳細度 = 100 */
CSSの参照方法で記述しているように、HTMLでは、当該要素の style属性値 として宣言を記述出来ます。この場合、詳細度100として考えます。これらの宣言は、すべての声明の後にあるものと考えて処理します。つまり、詳細度が同じ場合には、ほかの宣言を上書きします。例を見てみましょう。
<head>
<style type="text/css">
#x97z { color: blue }
</style>
</head>
<body>
<p id="x97z" style="color: red">一意セレクタ試験</p>
</body>
上の例の場合、p要素 は赤くなります。
セレクタの書き方、要素・属性の参照方法についてはセレクタの項、疑似クラスの書き方については疑似クラスの項、疑似要素の書き方については疑似要素の項をご覧ください。
- CSS1とCSS2の相違点
- 疑似要素の詳細度についてですが、CSS1では要素として数えました。CSS2では
要素として数えろ
という部分とゼロとする
という部分があり、どちらが正しいのかは例すらないので分かりません。
CSS以外の手段による体裁指定の取り扱い
難しい事を言っているようですが、例を挙げると、HTMLでは font要素 の face属性 や size属性、table要素 の align属性、center要素 等の事です。つまり、CSSで指定出来ますが、ソース文書の言語でも指定出来るスタイルの事です。CSS-HTML対比に該当する要素・属性の一覧があります。
これらは、すべて詳細度をゼロとして、すべての声明の前にあるものとして考えます。
- CSS1とCSS2の相違点
- CSS1では詳細度は1でしたが、CSS2では全称セレクタが新しく採用されましたので、その影響で0になりました。
詳細度、最重要宣言の関係
さて、では詳細度と最重要宣言、どちらを優先するのでしょうか。
CSSでは、
- 先ず出所と最重要宣言によるソート(つまり並べ替え)を行います。
- 次に、詳細度によるソートを行います。
- そして詳細度まで同じのものについては、より後に出現した側のものが適用します。
つまり、如何に詳細度が高くても、出所によるソートで既に負けている場合は、その宣言は適用されません。如何に詳細度が高くても、最重要宣言のほうが優先されます。
- 注意点
-
- link要素 と style要素 のカスケード方法は、CSS仕様書には書かれていません。HTML仕様書によると、どうやらそれらもソースにある順でカスケードするようです。