値わりあて,カスケード処理,継承

目次

指定値,算出値,実効値

User Agentは文書を解析して文書ツリーを組立てたのち,そのツリー内のあらゆる要素について,対象のメディアタイプに適用されるあらゆるプロパティに値を割り当てねばなりません。そしてプロパティの最終的な値は,次のような三段階の計算を経て与えられます:

  1. まづ指定された値そのものがあり:指定値(specified value)
  2. 次に必要ならば絶対値への変換を行い:算出値(computed value)
  3. 最終的にその場の環境制限に応じて実効値(actual value)を導き出す。

以降の節では,この三段階の計算によってどのようにプロパティの値が割り当てられるのか概説します。

指定値(Specified values)

User Agentはまづ以下の優先順に従って,プロパティに "指定値" を割り当てねばなりません:

  1. カスケード処理によって値を導けるのなら,それを指定値として用いる。
  2. さもなければ,そのプロパティが継承性を持つなら,親要素の値を用いる。一般にはその算出値。
  3. さもなければ,そのプロパティの初期値を用いる。初期値は各プロパティ定義に示してある。

文書ルート(HTMLではhtml要素)は親を持たないので,必要に応じて初期値が用いられます。

算出値(Computed values)

指定値が絶対値('red' や '2mm' など,他の値を参照しない)なら,算出値を導き出すための計算は必要ありません。

一般に継承には算出値が用いられますが,'line-height' の実数値では例外で,親要素の指定値を継承します。

実効値(Actual values)

User Agentは原則として最終的な値に算出値を用いるのですが,特定の環境ではその値を使用できないかもしれません。たとえばフォントサイズの算出値が '12.4pt' である場合,その大きさのフォントが手に入らなければ '12pt' などの近似値を採らざるを得ないでしょう。また,フォントサイズの制約が甚だしい環境では '10pt' や '14pt' などのように,算出値とかけ離れた近似値を強いられる事もあるでしょう。

すなわち実効値とは,このような場合に,算出値に対してあらゆる近似操作を処理したあとの値です。

CSS2.1での値わりあて

User Agentは文書を解析して文書ツリーを組立てたのち,そのツリー内のあらゆる要素について,対象のメディアタイプに適用されるあらゆるプロパティに値を割り当てねばなりません。CSS2.1では割り当て過程がひとつ増えて,四段階に変更されました:

  1. まづ指定された値そのものがあり:指定値(specified value)
  2. 次に継承のために使用される値に変換し:算出値(computed value)
  3. それから必要に応じて絶対値への変換を行い:使用値(used value)
  4. 最終的にその場の環境制限に応じて実効値(actual value)を導き出す。

以降の節では,この四段階の計算によってどのように値が割り当てられるのか概説します。

指定値(Specified values)

User Agentはまづ以下の優先順に従って,各々のプロパティに "指定値" を割り当てなければなりません:

  1. カスケード処理によって値を導けるのなら,それを指定値として用いる。
  2. さもなければ,そのプロパティが継承性を持ち,その要素が文書ルート以外なら,親要素の算出値を用いる。
  3. さもなければ,そのプロパティの初期値を用いる。初期値は各プロパティ定義に示してある。

算出値(Computed values)

指定値はカスケード処理の過程で算出値に解決されます; たとえば URI は絶対値がつくられ,'em' および 'ex' 単位はピクセルまたは絶対的な長さへと計算されます。値を算出する際,文書のレンダリングをUser Agentに要求することは決してありません。

指定されたURIについて,UAが "絶対URI" に解決できないなら,それは指定値のままになります。

プロパティの指定値が 'inherit' 以外であるときの算出値については,各々のプロパティ定義に示された 'Computed Value' 欄で述べられるとおり決定されます。指定値が 'inherit' であるときの算出値の定義については,後述する継承の節を参照してください。

'Applies To' 欄で定義されるようにプロパティが適用されない場合もありますが,それでも算出値は存在しています。しかしながら,いくつかのプロパティはその要素に該当するかどうか次第なので,その要素のためにプロパティの算出値を定めるかもしれません。

使用値(Used values)

算出値は可能なかぎり文書を整形せずに処理されます。しかしながら,いくつかの値は,文書がレイアウトされる時にのみ決定されます。たとえば,要素の幅がその包含ブロックの特定の割合で設定されている場合,その包含ブロックの幅が確定されるまで計算する事ができません。使用値とは,算出値および残りの依存状態のすべてを解決した,絶対値の結果のことです。

実効値(Actual values)

User Agentは原則としてレンダリングのために使用値を用いるのですが,特定の環境ではその値を使用できないかもしれません。たとえば,User Agentがボーダーをレンダリングする際に整数のピクセル幅しか扱えないような場合,算出幅を近似せざるを得ないでしょう。また,フルカラーの代りに白黒の明暗だけを使わざるを得ないような場合もあるでしょう。実効値とは,使用値に対してあらゆる近似操作を処理したあとの値です。

継承(Inheritance)

CSSではスタイル指定の軽量化と合理化を図るために継承(inheritance)と呼ばれる概念が導入されます。継承とは,プロパティの値が文書ツリーに沿って子要素に引継がれる仕組のことで,スタイルシートを効率よく記述するには缺かせない特徴のひとつです。

ただし,プロパティのスタイル効果に依っては継承しないほうが望ましい場合もあり,そのようなプロパティは継承されません。たとえば背景やボックスに関するプロパティは継承性を持ちません。各プロパティ定義には,そのプロパティの継承性の有無を明記してあります。

文書のデフォルト的なスタイル設定には,文書ルートなどへプロパティ指定をおこないます。たとえばHTML文書であれば,htmlまたはbody要素がその役割を擔います。この設定はソース文書内でbodyタグの記述が省かれた場合にも効果を持つことに注意せねばなりません(HTML 4文書ではbodyタグの記述を省略しても不正ではない)。なぜならHTMLパーサではbody要素の存在を推量して,文書ツリーを組上げるからです。

例1

次のごとく,文書のbody要素に対して'color'プロパティを宣言している場合で考えて見ましょう:

body { color: gray; }
<body>
  <h1>The headline is <em>important</em></h1>
</body>

もし上述のem要素に前景色が指定されてなければ,強調された important の前景色は,親のh1要素から継承するでしょう。さらにh1要素にも前景色が指定されてなければ,前景色をbody要素から継承するでしょう。つまり両者の前景色は灰色になります。

例2

次にあるパーセント値のような相対値なら,指定値そのものではなく,一般に算出値が継承されます:

body { font-size: 10pt }
h1   { font-size: 130% }
<body>
  <h1>A <em>large</em> heading...</h1>
</body>

上述のスタイルシートと文書断片で考えると,それぞれのフォントサイズは次の手順で算出されるでしょう:

  1. h1要素のフォントサイズは13pt(親である body の値 '10pt' の 130% 分)という算出値になる。
  2. 'font-size'プロパティは算出値を継承するので,em要素も上述同様13ptという算出値になる。

最終的に13ptのフォントが利用できないなら,両者はたとえば12ptなどの実効値を用いるかもしれません。

inherit という値(The 'inherit' value)

CSS2のあらゆるプロパティは,指定値として'inherit' という値を指定できます。これはその要素のそのプロパティが,親要素と同じ算出値を採るという効果をもたらします。明示的な 'inherit' の指定は,通常では継承しないプロパティでも,強制的に継承させます。

もしルート要素に対して 'inherit' を設定したなら,それはそのプロパティ自身の初期値にわりあてられます。

次の規則にある各プロパティは 'inherit' に拠って,親と同じ算出値を強制的に継承します。すなわち,font要素が持つデフォルトの体裁効果を無効にできます。もしこの規則がユーザスタイルにあれば,文書著者がマークづけしたfont要素を無効にできます。

font {
  color      : inherit !important;
  font-family: inherit !important;
  font-size  : inherit !important;
}

ある特別な要素においてその趣旨を徹すために,特定スタイルを子孫に亙って一貫させたいと考える事もあるでしょう。次例ではdel要素の子孫すべてについて前景色を強制継承させ,背景色を透明にさせています。すなわち,前景色と背景色が一貫します。

del {
  text-decoration: line-through;
  color: gray;
  background: #eee;
  padding: .5em;
}
del * {
  color: inherit !important;
  background: transparent !important;
}

(補足:ただし旧式ブラウザにおいては 'inherit' のサポートは不完全なので,無視されるかもしれません。したがって,このような宣言を制作者スタイルで用いると後方互換性に問題を来してしまうかもしれません。しばらくはユーザスタイルシートの規則だけで活用しておくのが無難かもしれません。)

@import規則(The @import rule)

@import規則を用いると,他のスタイルシートから多数の規則をインポートできます。(関聯:@規則

あらゆる@import規則は,スタイルシート内にある他種類のあらゆる規則(@charset規則が存在するならそれは除く)よりも先行せねばならず,@importキーワードの後には対象となるスタイルシートの URI が続かねばなりません; このURI指定については文字列の形式でもよく,それはurl()函数による指定と同じように解釈される事になります。そしてこの規則末尾にはセミコロン(;)を忘れずに記述してください。

著者はメディアタイプに依存した@import規則も指定できます。そういう条件つきのインポートは,URI指定の後にコンマ(,)区切りのメディアタイプを列記することで指定します。メディアタイプを明示しないなら,それは 'all' を指定した場合と同様に扱われます。

インポートされた規則は,ほかのあらゆる規則より先行した位置に記されているものとして扱われます。

次例では,多数のスタイルシートを特定メディアに依存させて,インポートしています。
@import url("general.css");
@import url('tv.css') tv;
@import "print.css" print;
@import 'bluish.css' screen, tv;

CSSに適合したUser Agentなら,ほかの規則よりも後の不正な@import規則を無視せねばなりません。

不正な例

ふたつめの '@import規則' について,ほかの規則よりも“後方”にあるので不正:

@import url("tv.css") tv;
body { font-size: medium; }
@import url("print.css") print;
p { line-height: 1.2; }

ふたつめの '@import規則' について,@mediaブロックの“内側”にあるので不正:

@import url("tv.css") tv;
@media print {
  @import url("print.css");
  body { font-size: 12pt; }
}

カスケード処理(The cascade)

スタイルシートには,次のような異る三通りの出処(origins)があります:

文書著者(Author)
著者は文書言語の約束に従って,ソース文書にスタイルシートを指定する; 制作者スタイルシート。たとえばHTML文書では,スタイルシートを文書内に埋込んだり,外部リンクで読込ませて,適用することができる。(see スタイルシートの適用
ユーザ(User)
ユーザがある特定の文書に対して任意のスタイルシートを指定できる場合がある; ユーザスタイルシート。たとえば,ユーザがスタイルシートを含むファイルを指定できたり,UAがユーザに対してスタイルを生成するインタフェイスを供給する場合もある。
ユーザエイジェント(User agent)
適合User Agentであれば他のどのスタイルシートよりもまづデフォルトスタイルシートを適用せねばならない(或いはそのように振舞う)。UAは文書の構造的な意図を満たすような一般的な表現方法で要素を示すべき(たとえば視覚系ブラウザでem,address要素がイタリックになるように)。HTML文書で推奨されているデフォルトスタイルシートについては,Default style sheet for HTML 4を参照のこと。

これらスタイルシートは同じ対象について競合を起すことがあり,そのような場合を回避するしくみをカスケード処理と謂います。CSSではカスケード処理に基いて各スタイル規則に優先度(weight)が割振られ,競合が生じる際には最優先の規則を適用します。

補足:ユーザに対して『文書著者の体裁を強いる』ことは不可能

最近のウェブブラウザには,ユーザ指定のスタイルシートを設定できる仕組が提供されています。これはCSS2仕様の適合性としてUser Agentがユーザに対して,個人のスタイルシートの選択手段を提供するよう推奨する(CSS2.1では大抵の場合サポートしなければならない;UAs must allow users to specify a file that contains the user style sheet.)と述べられているためです。

ユーザはこの機能を利用する事により,個人的・技術的な不都合を調節するためのスタイルシートを適用できます。更には最重要規則をユーザ側で指定することで,制作者スタイルシートの一部(あるいは全部)を上書きできるのです(下記参照)。すなわち,最終的な体裁制禦の権利はユーザ側に与えられているのであり,ユーザに文書著者の体裁を完全に強いることは不可能です

ウェブ内容の著者は,ユーザスタイルが適用しやすくなるよう,適切なマークアップを施した構造化文書を作成すべきです。また,ユーザ側でスタイルを適用しなくても済むよう,閲覧しやすい・利用しやすい,制作者スタイルシートを設計すべきです。

参考

〔補足終了〕

カスケードの順序(Cascading order)

ある要素とプロパティの組合せに適用する値を見出すために,UAは以下のソートを実行せねばなりません:

  1. 対象のメディアタイプに従って,問われる要素とプロパティに適用する宣言をすべて検索する。
  2. 始めに,宣言の重要性および出処でソートをおこなう。以下,優先が低い順に並べると:
    1. UAによるデフォルトの宣言
    2. 利用者による通常時の宣言
    3. 制作者による通常時の宣言
    4. 制作者による最重要の宣言
    5. 利用者による最重要の宣言
  3. 次いで,同一の重要性および出処である場合に,セレクタの詳細性でソートをおこなう。
  4. 最後に,指定された順序および場所によるソートをおこなう。

    (補足:HTML文書ではスタイルをlink要素もしくはstyle要素で適用でき,これらが競合します。一般的な実装ではstyle要素の中身のほうを後にあると見做し,外部スタイルの宣言より優先されます; ただし仕様書では明言されません。style属性については詳細性を参照のこと。)

特定の宣言に対する "!important" の設定を別にすれば,この計略は読者のスタイルより,制作者のほうに高い優先度を与えます。しかしCSS2.1適合のUAはユーザに対し,特定の制作者スタイルシートの影響をオフにする機能を提供する必要があります。

最重要規則(!important rules)

CSSでは,複数あるスタイルシートの間で勢力の均衡を創り出すために最重要宣言(宣言の後につづく !important で示される)が導入されます。文書著者およびユーザのスタイルシートには,どちらにも最重要宣言を含められ,ユーザスタイルシート内の最重要規則は,制作者スタイルシート内の最重要規則より優先します。また最重要宣言は,制作者スタイルシート内においても通常の宣言より優先します。

(補足:これは意味変更であり,CSS1ではユーザの最重要規則より,著者の最重要規則を優先していました。)

この特徴は,特別な表現(大きなフォント,色の組合せなど)を必要条件とするユーザにその制禦の手段を提供するので,文書のアクセシビリティを向上させる意図があります。特別な必要条件がなくとも,ユーザの主導権で読みやすく変更出来ることは有益です。

次例ではp要素に適用する各宣言について,!important を附加させています。
p {
  text-indent: 1em !important;
  margin: 1em .7em !important;
  line-height: 1.4 !important;
}

最重要指定の感歎符(!)と important の間には,記述の好みで自由に空白類文字を挿入できます。

セレクタの詳細性を計算する(Calculating a selector's specificity)

セレクタの詳細性(specificity)は以下のように計算します:

  1. セレクタを伴う規則よりstyle属性内の宣言を優先し,それをA=1とする(さもなくば=0
  2. セレクタ内にあるIDセレクタを数えあげ,それを B とする。
  3. その他の属性や擬似クラスを数えあげ,それを C とする。
  4. 要素型名および擬似要素を数えあげ,それを D とする。

これら四つの数字を ABCD と並べて詳細度とし,十分大きな基数の記進法で考えます。

詳細度の例
*             {} /* A=0 B=0 C=0 D=0 : 詳細度 =    0 */
LI            {} /* A=0 B=0 C=0 D=1 : 詳細度 =    1 */
LI:first-line {} /* A=0 B=0 C=0 D=2 : 詳細度 =    2 */
UL LI         {} /* A=0 B=0 C=0 D=2 : 詳細度 =    2 */
UL UL LI      {} /* A=0 B=0 C=0 D=3 : 詳細度 =    3 */
LI.class      {} /* A=0 B=0 C=1 D=1 : 詳細度 =   11 */
A[rel="up"]   {} /* A=0 B=0 C=1 D=1 : 詳細度 =   11 */
UL LI.class   {} /* A=0 B=0 C=1 D=2 : 詳細度 =   12 */
P.note.sp     {} /* A=0 B=0 C=2 D=1 : 詳細度 =   21 */
#id           {} /* A=0 B=1 C=0 D=0 : 詳細度 =  100 */
UL LI#id      {} /* A=0 B=1 C=0 D=2 : 詳細度 =  102 */
style=""         /* A=1 B=0 C=0 D=0 : 詳細度 = 1000 */

CSS以外の手段による表現指定の優先度(Precedence of non-CSS presentational hints)

UAは(特に視覚系ブラウザは),HTMLのソース文書内にある表現的属性について,その体面を保つかもしれません; たとえばfont要素の持つcolor属性のごとく。このような表現的属性については,詳細度 0 に相当するCSS規則として解釈されます。そしてそれらの規則は,制作者スタイルシートの先頭に挿入されるかのごとく扱われます。それ故にそれらは後続するスタイルシート規則により上書きされるかもしれません。

スタイルシートが普及するまでの移行期間,この方針は表現的属性とスタイルシートの共存を容易にするでしょう。CSS1仕様では,CSS以外の手段による表現指定の詳細度を 0 ではなく 1 としていました。これは詳細度が 0 である全称セレクタの導入に因ります。

CSS2.1仕様では表現的とされないHTML属性の一覧をしめして,明確化を図っています。(cf. CSS21-6.4.4