4. CSS syntax in detail

本章の目次

2・3章では,HTML文書からスタイル情報を締め出すことで,単純かつ一般性のある文書になることを解説しました。今後の章では(ようやく^^;),スタイル情報をスタイルシートとして構築する手順を解説します。

4章では,スタイルシート記述の文法的な側面を解説します。ただし,文法の全てを知っていなければスタイルシートを書けないか,といえばそうでもありません。先に6章「road to mastering CSS」を読み,関連する文法だけを抜き読みしても構いません。

なお,CSS2で新しく採用された仕様には「CSS2」である旨を明示します。今のところ,WWWブラウザはCSS2をサポートしていないことにご注意ください。

4.1. 記述のルール

4.1.1. 文字の扱い

CSS仕様のスタイルシートの記述は,大変に「定型的」です。すなわち,URLとフォントファミリーの指定を除き,あらかじめ規定されたキーワードを選択したり,数値を記入したりするだけでシートは完成します。

シートの一般様式は「要素名{プロパティ名:指定する値}」です。具体的なプロパティやその値に関しては5章で詳しく解説することにし,4章ではシートそのものを記述するための文法に関して解説します。

まず,スタイルシート記述に用いる文字に関する取り決めは次のとおりです。

4.1.2. スタイル指定の一般形式

専門用語として,「スタイル指定が適用される先」を「セレクタ(Selector)」とよび,「指定するスタイル内容」を「宣言(Declaration)」と呼びます。すると,シートの一般様式は

セレクタ{宣言}

になります。

端的には,セレクタはHTMLの要素そのものです。しかし,実際にはいくらかのバリエーションがあります。そのバリエーションを定めるのが「文法」です。まず,図4-1に正規の文法をいくらか簡略化したものを提示し,以降で各々のバリエーションについて解説していきます。

図4-1 CSSの基本文法
記述の説明:
< >
書くべきものの説明
( )
省略可能な語句
( )…
0回以上の繰り返し
|
orを表わす記号:どちらか一方のみを記述
/* */
コメント
それ以外
そのまま書く(ピリオド,コロンなど)
スタイル指定の一般式:
<セレクタ>(,<セレクタ>)… {<宣言>(;<宣言>)…}
/* セレクタはカンマ(,)で区切ることで,
   宣言はセミコロン(;)で区切ることで,
   グルーピングが可能。
*/
宣言:
<プロパティ値> : <値> (!important)
| /* 空の宣言も許されている */
/* !importantキーワードは,カスケーディング処理で使われる */

4.1.3. セレクタや宣言のグループ化

同じセレクタに対する宣言をまとめて記述する際には,宣言をセミコロン(;)でつないでグループ化して用います。また,同じ宣言を複数のセレクタにまとめて記述するには,セレクタをカンマ(,)でつないでグループ化します。

なお,分けて記述してもまとめて記述しても,意味は変わりません。

分けて記述した例:
P{font-weight: 500} /* 太さ500 */
P{text-align: left}
CITE{color: red}
STRONG{color: red}
CITE{font-style: italic}
まとめて記述した例:
P{
    font-weight: 500;
    text-align: left;
}  /* 最後の宣言にはセミコロンは不要ですが,
      付けても不正ではありません。*/
CITE, STRONG{color: red}
CITE{font-style: italic}

4.1.4. 宣言が衝突した場合の処理

宣言内容が衝突した部分――同じ要素・同じプロパティに複数の指定がなされた場合――は,後になされた宣言のみが有効になります。

受け取ったシート:
P{
    text-align: center;
    color: black;
}
P{
    text-align: left;  /* 同じ要素・同じプロパティの宣言が既にある */
}
有効になる宣言:
P{
    color: black;
}
P{
    text-align: left;  /* もっとも後ろのものが採用される */
}

ただし,!importantキーワードが付けられていた場合,優先順位は変動します。

受け取ったシート:
P{
    text-align: center !important;
    color: black;
}
P{
    text-align: left;  /* 同じ要素・同じプロパティの宣言が既にある */
}
有効になる宣言:
P{
    color: black;
}
P{
    text-align: center;  /* !importantのうち,もっとも後ろのものが採用される */
}

!importantキーワードは,後述のカスケーディング処理でも用いられます。

4.1.5. 属性値による対象の限定

1) CLASSとID

CSS1では,要素全般への指定だけでなく,HTML文書中でのID属性やCLASS属性の値を特定したスタイル指定が可能です。IDはシャープ(#)で,クラス名はピリオド(.)で指定します(CSS2では「#が取り扱うのは,はHTMLのID属性ではなく,属性値がID機能を持つすべての属性である」と拡張されています。この拡張は,XMLを考慮に入れたものでしょう)。

一般例:
<要素名>.<クラス名> {<宣言>}
<要素名>#<ID> {<宣言>}
宣言例:
BLOCKQUOTE{  /* クラス名を問わずに適用されるスタイル */
    font-style:italic;
    margin: 0.2em 2em; /* 上下マージン0.2em,左右マージン2em */
}
BLOCKQUOTE.BEATLES{color: red}  /* クラスBEATLESのみの追加スタイル */
BLOCKQUOTE.STONES{color: blue}

2) その他の属性による限定

CSS2では,CLASS,ID属性に限らず,全ての属性をもちいて対象セレクタを限定できるようになります。

要素名[属性名] ――その属性が宣言されている場合に有効。値は問わない。
A[HREF]{font-style: italic} /* リンク先を指定したアンカー */
A[NAME]{font-weight: bolder} /* 内部名を指定したアンカー */
要素名[属性名=属性値] ――その属性値が指定されている場合にのみ有効。
H1[ALIGN="CENTER"]{text-align:center;}
A[HREF="index.html"]{color: red;}
A[rel="NEXT"]{color: blue;}
要素名[属性名~=属性値] ――属性値がスペース区切りの値リストの場合に,その値の中に一つでも指定した属性値のものがあれば有効(主にCLASS属性)。
P[class~=LOVE]{color:red} 
    /* <P CLASS="LOVE"> や
       <P CLASS="LOVE PEACE SPECIAL"> の場合などで有効 */
要素名[属性名|=値] ――属性値がハイフン区切りの値リストの場合に,その値リストが指定した属性値で始まっていれば有効。主にLANG属性で,言語別に指定を切り分ける場合などに使う。4.1.8.(4)「:lang」疑似クラスとの違いに注意。
BLOCKQUOTE[lang|=fr] { quotes: '≪ ' ' ≫' }
    /* LANG="fr" や LANG="fr-FR" の場合などに有効 */
BLOCKQUOTE[lang|=ja] { quotes: '「' '」'}
    /* LANG="ja" や LANG="ja-JP" の場合などに有効 */

3) クラス名による限定の拡張

CSS2では,一つの要素に複数のクラスが指定されていることを勘案し,クラス名へのアクセスを強化しました。

「要素名.クラス名1.クラス名2」――クラス名を複数指定した場合,class属性値の並びの中に指定した全てのクラス名を含んでいる場合のみ有効。
P.LOVE.PEACE{color:red}
    /* <P CLASS="LOVE"> では無効だが,
       <P CLASS="LOVE PEACE SPECIAL"> では有効 */

4) 要素名を指定しない宣言

CSS1では,IDやクラス名だけを指定した宣言(要素名を省略した宣言)を行ったならば,すべての要素に関する指定を行ったことになります。

要素を問わない指定の一般形式:
.<クラス名>{<宣言>}
#<ID>{<宣言>}
例:
/* BLOCKQUOTEでもPでも, CLASS="BEATLES" ならば色を変える */
    .BEATLES{color: red}
/* 要素は問わずに ID="CHAPTER2" に指定 */
    #CHAPTER2{color: blue;}

CSS2では,要素名を「*」と書いた場合に,「すべての要素に対する宣言をした」と解釈することに変更されました。なお,上位互換のため,CSS1と同じ記述方法も可能です。

CSS2における「*」は過度に強力な仕組みで,4.2.で説明する「継承」の利点を無視した指定すら可能になります。使用する際には,本当に必要なのかどうかを十分検討してください。

例:
/* 強制的に,すべての要素の色を指定 */
    * {color: black; background: white}

4.1.6. CSS1における文脈判断

普通のスタイル宣言は,指定した要素が文書中のどこに現れても全てに適用されます。すなわち,

STRONG{color: red;}

とさえ記述すれば,STRONG要素がH1中に現われようとP中に現われようと,文脈を問わずに赤色になります。

しかし,「見出しの中のSTRONG要素だけ色を変えたい」ケースもあるでしょう。例えば,H1要素も「color: red」と指定されているため,同じSTRONGでも「H1に含まれる場合だけ」青色にしたいというケースが考えられます(図4-2)。

CSS1では,「対象要素が特定の親要素に含まれた場合にのみ有効になるスタイル」を,「親要素」「子要素」の順に「スペース」で区切って並べたセレクタを用いて指定できます。これを文脈付きセレクタ(Contextual Selector)と呼びます。

一般形式:
親要素 子要素 (孫要素)…{<宣言>}
図4-2 H1に含まれるSTRONGだけへの追加指定
/* 単純宣言 */
    BODY{
        color: black;
        font-size: 10pt;
    }
    H1{
        color: red;
        font-size: bolder;
        text-decoration: underline;
    }
    STRONG{  /* 全てのSTRONGに適用されるスタイル */
        color: red;
        font-style: italic;
    }
/* H1に含まれるSTRONGだけに対する“追加の”スタイル */
    H1 STRONG{color: blue;}
<H1>私の<STRONG>趣味</STRONG>について</H1>
<P>私の趣味は<STRONG>音楽</STRONG>です。</P>
【図4-2】――通常のSTRONGは赤ですが,H1はそれ自身が赤なので,H1の中のSTRONGを青で表現しています。

4.1.7. CSS2における文脈判断

CSS2では,文脈判断がCSS1よりも数段強力になりました。

1) 子孫セレクタ(下降セレクタ,descendant selector)

これは,CSS1における文脈付きセレクタと全く同じものです。4.1.6.では明言しませんでしたが,子孫セレクタにおける「親子関係」は,直接の「子」には限定されません。例えば,「BLOCKQUOTE STRONG」とはBLOCKQUOTE要素に含まれる全てのSTRONG要素に対する指定であり,次のSTRONG要素にも適用されます。

<BLOCKQUOTE>
    <P>私の趣味は<STRONG>音楽</STRONG>です。</P>
</BLOCKQUOTE>
コラム:文脈指定がぶつかった場合

もし,「BLOCKQUOTE STRONG」と「P STRONG」の両方にスタイルを宣言していれば,上記の文脈では両方が同時に有効になります。ただし,衝突する宣言に関しては,より内側の文脈――この場合は「P STRONG」――に対する宣言が優先されます。

存在する指定:
BLOCKQUOTE STRONG{
    color: black;
    font-weight: bold;
}
P STRONG{
    color: red;
}
実際に「BLOCKQUOTE P STRONG」に適用される指定:
{
    font-weight: bold;
    color: red;
}

2) 子セレクタ(child selector)

子孫セレクタとは異なり,ある特定の要素が直接の親要素になった場合にだけ有効になる宣言を行いたい場合は,この「子セレクタ」を用います。

一般形式:
親要素 > 子要素 {<宣言>}
宣言例:
DIV.BEATLES > P {font-family: sans-serif;}
例ソース:
<P>もちろん,僕だってBEATLESは嫌いじゃない。<!-- ←ここには適用されない -->
<DIV CLASS="BEATLES">
    <P>好きなのは,初期のロックもの。ハード・デイズ・ナイトなどには感涙。
    しかし,次にリストアップする曲は嫌い。<!-- ←ここには適用される -->
    <UL>
        <LI><P>イエスタデイ <!-- ←ここには適用されない -->
        <LI><P>ヘイ・デュード <!-- ←ここには適用されない -->
        <LI><P>ロング・アンド・ワインディング・ロード <!-- ←ここには適用されない -->
    </UL>
    <P>中期以降でも,やはりサージェント・ペパーズなどは好き。<!-- ←ここには適用される -->
</DIV>

3) 隣接セレクタ(Adjacent sibling selector)

親子関係ではなく,文書中の連続関係に注目したのが「隣接セレクタ」です。たとえば,「H1要素直後のH2要素」などに指定したい場合に用います(一般に,見出しが上位の見出しに連続する時と地の文章に続く場合とで,マージンなどを変えるのはもっともです)。

一般形式:
直前要素 + 直後要素 {<宣言>}
宣言例:
H2{margin-top:1em;}
H1 + H2{margin-top:0em;}
例ソース:
<H1>すみけんリソース!</H1>
<H2>前書き</H2> <!-- ←ここはH1+H2 -->
<P>うんぬんかんぬん

<H2>目次</H2> <!-- ←ここはただのH2 -->
<UL>
    <LI><P><A HREF="first>うんぬん</A>
    <LI><P><A HREF="second">かんぬん</A>
</UL>

4) 複雑な指定の場合の優先順序

各種文脈の指定は,複数の種類を混ぜることが可能です。その場合でも,指定は単純に前から(あるいは後ろから)順に読み解くだけであり,特別な優先順位は存在しません。

BLOCKQUOTE DIV.BEATLES > P STRONG {color: red}
/* (前から読み解くと……)
       「『BLOCKQUOTE要素の内部にある,CLASS="BEATLES"を指定されたDIV要素』の,
          直接の子要素であるP要素」
        の内部にあるSTRONG要素に対して適用される。 */
/* (後ろから読み解くと……)
       STRONG要素に適用される。
       ただし,そのSTRONG要素がP要素の内部にあることと,
       そのP要素がDIV要素の直下の子要素であることと,
       そのDIV要素がBLOCKQUOTE要素の内部のもので
       しかもクラス名として"BEATLES"が指定されていることが条件。*/

4.1.8. 疑似クラス

1) 疑似クラス(pseudo-class)とは

WWWにとって有用な情報が,必ずしもHTML文書インスタンスそのものから判断できるとは限りません。例えば,アンカーには「まだ表示したことの無いリンク」「既に表示したことのあるリンク」などの性質の違いがあり,その性質に応じてスタイルを変えることは合理的ですが,その違いはWWWブラウザの履歴情報によって始めて分かるものです。したがって,いくらHTML文書を眺めても判断できません。

このような場合に活用されるのが「疑似(pseudo)クラス」です。「疑似クラス」は,文書中には実在しない性質に着目してスタイルを宣言するための手段です。

2) リンク疑似クラス(link pseudo-class)

CSS1では,上述した「アンカーに対する3つの疑似クラス」のみが用意されています。

:link
まだ表示したことのないURLを指すリンク
:visited
既に表示したことのあるURLを指すリンク
:active
ユーザが選択中のリンク(マウスで触っている等)

疑似クラスへのスタイル宣言は,要素名と疑似クラス名をコロン(:)でつないで記述します。

A:link{color: bule}
A:visited{color:lime}
A:active{color:red; background: #e88;}

3) ダイナミック疑似クラス(dynamic pseudo-class)

CSS2では,リンク疑似クラスを「:link」と「:visited」の二つに限定し,あらたに「ダイナミック疑似クラス」として「:active」「:hover」「:focus」の3つを導入しました。

:active
現在選択中の要素(マウスで触っている,スペースキーを押している,など)
:hover
マウスなどがその上に来ている要素
:focus
キーボードなどでフォーカスが与えられた要素

疑似クラスを複数用いることによって,「リンク済みでアクティブ」「未リンクでアクティブ」を表現できます。

A:link:active{color:white; background: #555}
A:visited:active{color:red; background: #955}

:focusは,HTML4.0で強化されたアクセスキー(キーボードショートカット)設定に対応するもので,フォームやリンクで活用されるでしょう。また,outlineプロパティと:focus疑似クラスを組み合わせることで,イメージマップのうちの選択中の部分に枠を付けるなどの表現も可能になります。

なお,リンク疑似要素はアンカー専用の疑似要素でしたが,ダイナミック疑似要素はすべての要素に適用されます。例えば,「マウスをかざした部分だけ色が変わる目次」などに応用が可能です。

UL.CONTENTS LI:hover{color:black; background:#f8f;}

4) 言語疑似クラス(:lang() pseudo-class)

CSS2で追加された疑似クラスで,言語属性を表現するものです。引用符記号など,言語に依存する表現を使い分けたい時に有用です。(文書の言語属性は,対象となる要素に直接LANG属性が指定されていなくても,親子関係などから判断可能です。この意味で,[lang|=fr]などとは適用範囲が異なります。)

:lang(fr) > Q { quotes: '≪ ' ' ≫' }
:lang(ja) > Q { quotes: '「' '」'}

5) 「最初の子」疑似クラス(:first-child pseudo-class)

CSS2で追加された疑似クラスで,同列の子要素のうち,文書中の順序が一番始めである要素を表現するものです。

例:
P > STRONG:first-child{ color: red}
<P>いいですか,僕が
<STRONG>「オイッス」</STRONG><!-- ←ここには適用される -->
といったら,みんなも「オイッス」と応えるのが礼儀です。
また,儀式として,僕は
<STRONG>「声が小さい,もう一度!」</STRONG><!-- ←ここには適用されない -->
と言い返すので,ここで皆さん笑ってください。

4.1.9. 疑似要素

1) 疑似要素とは

疑似要素も,疑似クラスと同様に,実際には文書中に存在しない要素を操作するものです。あえて性格を要約すれば,書こうと思えば文書中に記述できるが,規則性を持って自動処理することが望ましいもの」が疑似要素に設定されています。

疑似要素へのスタイル宣言も,疑似クラスと同じく,要素名と疑似クラス名をコロン(:)でつないで記述します。

2) 「はじめの文字(:first-letter)」「はじめの一行(:first-line)」

CSS1では,「はじめの文字(:first-letter)」「はじめの一行(:first-line)」のふたつの疑似要素が用意されています。その名のとおり,「はじめの文字」「はじめの一行」だけを異なる見栄えで表示したい場合に利用します(図4-3)。

図4-3 first-letter疑似要素の使用例
H1:first-letter{font:2em fantasy}
“<H1>History of WWW</H1>”の表示イメージ:
Historyの"H"の文字だけが飾り文字になっています。

3) 「前(:before)」「後(:after)」

CSS2で追加された疑似要素で,各要素の前後に,自動的に文字などを挿入したい場合に用います。各疑似要素で表示したい内容は,専用のプロパティ「content」で指定します(7.2.1を参照)。

H1:before{content: "−章−"; font-size: 1.5em; display:block;}
BLOCKQUOTE:before{content: open-quote}
BLOCKQUOTE:after{content: close-quote}
BODY:after{content:"以上,終了。"; margin-top: 5em;}

4.1.10. @mediaブロック

例えば,一般的な画面(screen)と異なり,文字端末(tty)では文字色・サイズを一定にして表現しなければなりません。このような場合,メディアごとに指定値を切り替える必要があります。CSS2では,メディアを指定してシートを記述するために,@mediaブロックを用意しました。

CSS1には@mediaに相当する仕組みはありませんが,シートの想定メディアはHTMLのLINK要素で指定すればよいため,特に困りません。互換性確保のこともあり,今のところは一つのシートは特定のメディアのみを想定して記述しておき,HTML文書からメディアを指定するほうが得策でしょう。なお,具体的なメディアの特徴およびLINK要素に関しては4.3.5.を参照してください。

@media screen{
    H1{ font-size: 3em}
    H2{ font-size: 2em}
}
@media screen, tty{
    H1{
        text-align: right;
        margin-top: 2em;
    }
    H2{
    text-align: center;
    margin-top: 1em;
    }
}

4.1.11. @import宣言

スタイルシートは,基本的にはテキストファイルとして作成・保存されています。各々のシートどうしは独立した存在ですが,あるシートに別のシートを取り込むことも可能です。

コラム:拡張子「.css」

CSSによるスタイルシートファイルの拡張子は「.css」としてください。これはコンテントタイプ(MIMEタイプ)指定“text/css”と絡んだ取り決めです。くわしくは,RFC2318を参照してください。

@importキーワードは,既存のスタイルシートファイルの取り込みを宣言します(注:C言語の#includeに似ています。)。WWWブラウザは,受け取ったスタイルシートファイルに@importが書かれていれば,そのシートも同時に読み込みます。

@importの指定法:
@import "スタイルシートを指すURL";
@import url(スタイルシートを指すURL);

@importで取り込んだ後に独自の宣言を書き込むことで,指定を追加・上書きできます。

@import url(http://www.w3.org/pub/WWW/def-style.css);
@import url(my-style.css);
STRONG{color: red}  /* このシート独自の追加宣言 */

@importを複数指定することも可能ですが,シート独自の追加宣言よりも前に記述する必要があります。なお,@importで取り込んだシート間で宣言が衝突した場合は,単純にもっとも後ろに書かれた宣言のみが有効になります(4.1.4.を参照)。

4.2. 継承とカスケーディング

4.2.1. 継承(inheritance)の利点

HTML文書インスタンスは多くの要素の集合です。また,スタイルシートで調整できるプロパティも多岐にわたります。では,全ての要素に全てのプロパティについての指定を行わなければならないのでしょうか?

指定の軽量化と合理化のために,CSSは「継承」という仕組みを提唱しています。継承とは,HTML文書インスタンスの構成に沿って,親要素から子要素へスタイルを伝播させる仕組みです。

具体例を用いて説明しましょう(図4-4,4-5)。

例:
<BODY>
<H1>日記<STRONG>1997年11月24日</STRONG></H1>
<P>TVで偶然に<STRONG>西行法師</STRONG>の短歌を聞いた。</P>
<BLOCKQUOTE>
    <P>「ねがわくば,桜の元で,春死なん」</P>
</BLOCKQUOTE>
<P>本当はこの後に下の句が続くのだが,忘れてしまった。
しかし,これだけでも大変見事に「日本人の風情」を表現していると思う。</P>
</BODY>
BODY{
    color: black;
    font-size:10pt;
}
H1{
    font-size:15pt;
    font-family: sans-serif;  /* ゴシック系を期待 */
}
BLOCKQUOTE{font-style: italic}
STRONG{font-weight: bold}
図4-4 例文書の文書構造
【図4-4】――HTML文書は要素の親子関係から成り立っているので,要素の「家系図」のようなものを書くことができます。
図4-5 スタイル適用例
【図4-5】――「家系図」での「親」からスタイル宣言を継承した上で自分自身への宣言を追加または上書きして,最終的なスタイルが決定されます。

この文脈におけるH1は,まずBODYの宣言を継承し

color: black;
font-size: 10pt;

に設定されます。その後,自分への宣言を追加・上書きします。したがって,結果として

color: black;
font-size: 15pt;
font-family: sans-serif;

を採用します。

図4-5におけるH1に関するスタイル宣言は,「フォントサイズとファミリーの変更は必要だが,色に関してはこだわらない」という考えで記述されています。すると,色は「継承」によって親要素のものが自動的に適用されるのです。すなわち,シート記述者は,必要な要素に対して必要なプロパティのみを宣言するだけで良いのです。

「継承」のこの利点により,スタイルシートは簡潔でわかりやすいものになるでしょう。

次にSTRONG要素を見てみましょう。一口にSTRONG要素といっても,「H1に含まれているSTRONG(1)」と「Pに含まれているSTRONG(2)」とでは,それぞれ継承する親要素が異なるため,最終的に採用するスタイルが異なります。明示するならば次のようになります。

STRONG(1){
    color: black;  /* H1…BODY */
    font-size: 15pt;  /* H1 */
    font-family: sans-serif;  /* H1 */
    font-weight: bold;
}
STRONG(2){
    color: black;  /* P…BODY */
    font-size: 10pt;  /* P…BODY */
    font-weight: bold;
}

各要素の親要素は固定ではなく,HTML文書の文脈によって変ります。この全てのケースを明示してスタイルを調整していくのは大変です。しかし,「継承」によってこれらは自動的に調整されるのです。これも「継承」の利点としてあげて良いでしょう。

H1{
    color: black;
    font-size:15pt;
    font-family: sans-serif;
}
BLOCKQUOTE{
    color: black;
    font-size:10pt;
    font-style: italic;
}
P{
    color: black;
    font-size:10pt;
}
H1 STRONG{
    color: black;
    font-size:15pt;
    font-family: sans-serif;
    font-weight: bold;
}
P STRONG{
    color: black;
    font-size:10pt;
    font-weight: bold;
}
BLOCKQUOTE P{
    color: black;
    font-size:10pt;
    font-style: italic;
}

もし「継承」の仕組みが存在しなければ,必要となる全ての文脈に関してあらかじめスタイルを宣言するはめに陥ります。しかも,文書が異なれば必要な文脈は変わってしまうため,「特定のHTML文書にしか利用できない」スタイルシートが出来上がるでしょう。このように考えてみると,「継承」はシートの汎用性・再利用性の確保にも役立っています。

さらに,「全ての文脈について,全てのプロパティを宣言している」場合に,H1要素のフォントサイズを変更したくなったとしたら,関連して幾つの宣言を修正することになるでしょう? この例では「H1 STRONG」だけですが,文書が異なれば更に増える可能性があり,修正はだんだんと面倒なものになるでしょう。このように考えると,「継承」はメンテナンスしやすさ――メンテナンス性――の向上にも役立っています。

シート記述者は,「継承」という単純なルールが産み出すさまざまな利点を十分意識する必要があるでしょう。

コラム:宣言記述の順

継承はあくまでもHTML文書インスタンスの入れ子構造にしたがって行われるので,宣言記述の順番を入れ替えても継承処理には何の影響もありません。

P{
    color: white;
}
BODY{
    font-size: 12pt;
    color: red;
}

この場合でも,P要素は先にBODY要素から指定を受け継ぎ(BODYは本文の最上位の親要素ですから,常にその指定は継承されます),その後P要素に直接指定された宣言を受け入れます。したがって,Pのcolorプロパティは上書きされてwhiteとなります。

しかし,「後に書かれた方が有効になる」ように注意して書いたほうがわかりやすいのでは無いでしょうか。

BODY{
    font-size: 12pt;
    color: red;
}
P{
    color: white;
}

このように書かれていた方が,「PはBODYの子要素であり,BODYの指定を継承する。継承した上で,colorは上書きされる」という関係が理解しやすいと思われます。筆者は,文書型定義における親要素から順に宣言を記述することを奨励します。

4.2.2. 継承されないプロパティ

継承は大変便利な仕組みですが,全てのプロパティが継承されるわけではありません。なぜなら,継承するべきでないプロパティも存在するからです。継承されるのか否かは,プロパティごとに仕様書で定められています。

例えば,背景画像の指定は継承されません。仮にBODYの背景画像がPに継承されたとすると,Pが現われるたびに背景が書き直され,図4-6に示すような結果になります。どちらかといえば,「背景画像の付け直し」よりも「既に表示されている背景の上に文字を表示する」方が,即ち,背景は継承されないほうが標準的だと考えられます。(CSSのbackground-colorプロパティの初期値はtransparent(透明)になっており,親要素の背景をそのまま表示することが想定されています。)

図4-6 背景が継承されるとしたら
【図4-6】――背景が継承されてしまうと,例えば段落が始まるたびに,また段落中に強調があるたびに,新たに背景が再配置されてしまいます。

また,“直前のテキスト”との垂直位置関係(上付き下付き)も継承されません。例えば,図4-7のHTMLコードのSUPの上付き効果をSTRONGが継承してしまえば,結果は「上付きの上付き」すなわち「eの(2のx乗)乗」のように表示されてしまいます。

図4-7 eの(2のx乗)乗?
e<SUP>2<STRONG>x</STRONG></SUP>
【図4-7】――「上付き」が継承されてしまうと、「eの2x乗」のつもりが「eの(2のx乗)乗」のように見えてしまいます。

4.2.3. カスケーディング(cascading)とは

CSSの仕様は,HTML文書に対して「WWWブラウザ標準のスタイルシート」「ユーザ(読者)が標準とするスタイルシート」「HTML文書作成者が指定するスタイルシート」の3つのスタイルシートが用意され,この3者の指定を融合させることを想定しています。この3種類のスタイルシートの宣言の融合法,指定が衝突したときの混乱解消法を“カスケーディング”と呼びます。

CSSが想定するカスケーディング処理の基本は,単純で明快です。

CSSでは,各スタイルシートの指定に優先順位をつけています。それを数学の大小記号であらわすと,「WWWブラウザ」<「ユーザ(読者)」<「HTML文書作成者」です。それぞれのスタイルシート間で衝突するプロパティ値が宣言されているときは,優先順位が高い方の指定だけを採用します。宣言が衝突しない場合は,単にそれを採用します。これが,カスケーディング処理の基本です。(全てのカスケーディング処理が終わった後,スタイルの継承が処理されます。それでも指定されていないプロパティがあれば,CSS仕様に定められる初期値が採用されます。)

この処理には以下の利点が挙げられます。

WWWブラウザ標準:
BODY{
    line-height: 1em;
    color: black;
}
ユーザ(読者)標準:
BODY{
    line-height: 1.3em;
    color: white;
    background: black;
}
HTML文書作成者指定:
BODY{line-height: 1.5em}
採用される値:
BODY{
    line-height: 1.5em;  /* 作成者の値 */
    color: white;  /* ユーザ(読者)の値 */
    background: black;  /* ユーザ(読者)の値 */
} /* そのほかのものは,初期値が採用される */

ただし,スタイル宣言に「!important」キーワードをつけた宣言に関しては,優先順位が変ります。「HTML文書作成者」<「!important付きHTML作成者」<「!important付きユーザ(読者)」となります。(これはCSS2の仕様です。CSS1では,「HTML文書作成者」<「!important付きユーザ(読者)」<「!important付きHTML作成者」となっていました。)

WWWブラウザ標準:
BODY{line-height: 1em}
ユーザ(読者)標準:
BODY{
    line-height: 1.3em !important;
    color: black;
}
HTML文書作成者指定:
BODY{
    line-height: 1.5em;
    color: red;
}
採用される値:
BODY{
    line-height: 1.3em;
    color: red;
}

ところで,セレクタの指定にクラスやIDなどが絡んでくると,カスケーディング処理は複雑になります。本書では,このケースに関しての解説は省略します。

コラム:ユーザ(読者)標準スタイルシートの例

これまでのところ,Netscape NavigatorやInternet Explorerの標準的な見栄えでは,行幅に余裕がありません。行幅はスタイルシートによって自在に変更できるのですが,いまだシートを使っていないHTML文書も数多く公開されています。文書作成者がシートを付けてくれるのを待つよりも,自分で「ユーザ(読者)標準スタイルシート」を用意してしまうほうが賢いでしょう。

筆者が使っている「ユーザ(読者)標準スタイルシート」は,次のように簡単なものです。これ以上ごちゃごちゃと指定してしまうと,HTML文書作成者のシートとの兼ね合いが上手く行かなくなってしまうからです。

/* default.css */
BODY{
    font-size: 11pt !important;
    line-height: 1.5;
}

なお,Netscape Navigator4.0には,ユーザ(読者)標準シートを設定する機能が無いようです。Internet Explorer4.0には,メニューの「表示→インターネットオプション」で開かれる設定ダイアログの「全般」のなかの「ユーザ補助」に設定項目があります。

4.3. HTML文書との連携

スタイルシートとHTML文書の連携に関する取り決めは,CSSの仕様ではなくHTMLの仕様の範疇に入ります。HTML4.0の仕様には,CSSだけでなく,他の仕組みのスタイルシートを包括した「スタイルシートとの連携方法」が記載されています。(2.0,3.2の仕様のHTML文書でも,同様にLINK要素を用いてスタイルシートと連携させられると考えてもよいでしょう。)

4.3.1. 連携方式の分類

HTML4.0は,スタイルシートの連携方式を3つ想定しています。機能的な違いは「いつ有効になるのか」だけです。

persistent(永続)スタイルシート
常に有効になるスタイルシートです。(ただし,WWWブラウザのスタイルシート機能をオフにすれば,persistentシートもオフになります。)
preferred(おすすめ)スタイルシート
ユーザが何も指示しない場合に限り有効になるスタイルシートです。HTML文書読み込み時には全て有効になっていますが,特定のタイトル名のシートだけを有効にするよう切り替えることが可能です。
alternate(代替)スタイルシート
ユーザが特に指示した場合に限り有効になるスタイルシートです。HTML文書読み込み時には全て無効になっていますが,特定のタイトル名のシートだけを有効にするよう切り替えることが可能です。

4.3.2. LINK要素で外部スタイルシートと連携

LINK要素を用いれば,独立したファイルとして保存されているスタイルシートをその文書と連携させることが可能です。ファイル名はHREF属性で指定します。シートとの連携方式は,REL(Forward Relationship)属性とTITLE属性をもちいて指定します。スタイルシートの種類はTYPE属性で(CSSであれば“text/css”と)指定します。

「REL="STYLESHEET"」とする場合
TITLE属性を省略したものはpersistent(永続)スタイルシートになります。
TITLE属性を明示したものはpreferred(おすすめ)スタイルシートになります。
「REL="ALTERNATE STYLESHEET"」とする場合
alternate(代替)スタイルシートになります。TITLE属性を明示しなければいけません。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4,0//EN">
<HTML>
<HEAD>
<TITLE>HTML4.0(W3C Recommendation 18-Dec-1997)解説</TITLE>
<LINK REL="STYLESHEET" TYPE="text/css" HREF="normal.css">
<LINK REL="STYLESHEET" TITLE="fancy" TYPE="text/css" HREF="fancy.css">
<LINK REL="ALTERNATE STYLESHEET" TITLE="compact" TYPE="text/css" HREF="small.css">
<LINK REL="ALTERNATE STYLESHEET" TITLE="compact" TYPE="text/css" HREF="mini.css">
</HEAD>
コラム:WWWブラウザの振る舞い

WWWブラウザは,読み込んだHTML文書にスタイルシートファイルが指定されている場合,そのシートも自動的に読み込みます。そして,連携方式を判断し,適切なシートだけを有効にした上で表示を調整します。

4.3.3. 有効スタイルシートの切り替え

preferred(おすすめ)およびalternate(代替)のスタイルシートには,TITLE属性によってタイトル名が指定されています。ユーザは,その中の特定のタイトル名を指示することによって,有効になるスタイルシートを切り替えることが可能です。

特定のタイトル名が指定された場合,そのタイトル名でないpreferred(おすすめ)スタイルシートは無効になり,そのタイトル名のalternate(代替)スタイルシートは有効になります。なお,persistent(永続)スタイルシートは常に有効です。

<LINK REL="STYLESHEET" TYPE="text/css" HREF="normal.css">
<LINK REL="STYLESHEET" TITLE="fancy" TYPE="text/css" HREF="fancy.css">
<LINK REL="ALTERNATE STYLESHEET" TITLE="compact" TYPE="text/css" HREF="small.css">
<LINK REL="ALTERNATE STYLESHEET" TITLE="compact" TYPE="text/css" HREF="mini.css">

この例の場合,文書読み込み時にはpersistent(ここではnormal.css)とpreferred(ここではfancy.css)の2つのスタイルシートが有効になっています。ユーザの指示により「compact」が選択されれば,prefrredとalternateのうち「compact」のタイトル名を持つスタイルシート(ここではsmall.cssとmini.css)に加えてpersistentが有効になり,他のシートは無効になります。

なお,複数のスタイルシートに同じタイトル名を付けた場合,そのシート群は同時に有効/無効になります。

コラム:WWWブラウザの振る舞い

有効スタイルシートの切り替えをどのような方法で行うのかはWWWブラウザに一任されています。プルダウン・メニューの一覧から選ぶ,別ウィンドウに示されるリストから選ぶなどのバリエーションが考えられます(図4-8)。

図4-8 スタイルシート選択ウィンドウ(想像図)
各スタイルシートのタイトル一覧から,適用するスタイルを選択します。

どのような方法をとるにせよ,CSS対応を名乗るWWWブラウザは,少なくとも指定されているスタイルシートのタイトル名一覧(ファイル名ではない)をユーザに提示できなければいけません。それにもかかわらず,Netscape Navigator4.0,Internet Explorer4.0はスタイルシート選択機能をサポートしていません。

4.3.4. 複数のスタイルシート間で宣言が衝突した場合

複数のスタイルシートが有効になっている場合には,シート間で宣言が衝突する可能性があります。衝突した場合には,単純にHEAD要素中での出現順位がもっとも後ろである宣言のみが有効になります(「4.1.4. 宣言が衝突した場合の処理」を参照)。

4.3.5. 有効メディアの区別

HTML文書の再生メディアは,必ずしもコンピュータのスクリーン(ページの継ぎ目はなく,表示しきれない部分はスクロールバーによって調整する)であるとは限りません。場合によっては音声出力(スピーチ・シンセサイザー)であったり印刷(ページの物理的な区切りに制約される)であったりしても何の不思議もありません。HTML4.0の仕様書には,表4-1に示すメディアの種類が紹介されています。

表4-1 スタイルシートのメディア指定
説明
SCREENスクロール可能な(ページの区切り目の無い)コンピュータ画面
TTYテレタイプや端末画面など,固定ピッチ文字によるコンピュータ画面
TV家庭用TVセットのモニタ
PROJECTION投影機
HANDHELD小型情報機器(画面サイズや色に制限が多いもの)
PRINT紙,あるいはページ区切りのあるコンピュータ画面
BRAILLE点字
AURAL音声出力(スピーチ・シンセサイザー)
ALL全て

再生メディアが異なれば,望ましい再生スタイルも異なります。したがって,スタイルシートはメディア別に指定されているべきです。その指定は,HTML文書中に「このメディアの場合はこのシートを用いる」という形態で行います。これは,LINK要素にMEDIA属性を指定することで実現されます。(一つのスタイルシートに複数のメディアを指定する場合は,カンマ(,)で区切って並べます。)

<LINK REL="STYLESHEET" MEDIA="ALL" TYPE="text/css" HREF="normal.css">
<LINK REL="STYLESHEET"  MEDIA="AURAL" TYPE="text/css" HREF="normal-vox.css">
<LINK REL="STYLESHEET" TITLE="fancy" MEDIA="SCREEN"
    TYPE="text/css" HREF="fancy.css">
<LINK REL="STYLESHEET" TITLE="compact" MEDIA="SCREEN, HANDHELD" 
    TYPE="text/css" HREF="small.css">
<LINK REL="ALTERNATE STYLESHEET" TITLE="slow-vox" MEDIA="AURAL" 
    TYPE="text/css" HREF="slow-vox.css">

もし,WWWブラウザが音声出力用に設定されていれば,AURALとALL以外のメディアのスタイルシートは常に無効になるでしょう。この場合はpersistent(永続)としてnormal.cssとnormal-vox.cssが,alternate(代替)として「slow-vox(slow-vox.css)」のみが採用されるでしょう。(Netscape Navigator4.0,Internet Explorer4.0はメディア選択機能をサポートしていません。)

4.3.6. STYLE要素で文書内にスタイルシートを記述

HTML3.2からは,HTML文書内にスタイルシートを直接記述するためのSTYLE要素が用意されています。LINK要素と同様に,TYPE属性,MEDIA属性,TITLE属性を指定できます。

<HEAD>
<TITLE>test</TITLE>
<STYLE MEDIA="ALL" TYPE="text/css">
    BODY{
        color: white;
        background: black;
    }
</STYLE>
</HEAD>
コラム:スタイルシートをコメントアウト

HTML3.2以上の仕様を解釈しないWWWブラウザは,STYLE要素の中身を単なるテキストとして表示してしまうかもしれません。W3Cは,それを避けるために,STYLE要素の中身をHTML文書としてコメントアウトするよう提案しています。

<STYLE TYPE="text/css">
<!--
    BODY{
        font: 400 medium serif; /* 太さ400,サイズ普通,ひげ付き文字 */
        text-align: left;
    }
-->
</STYLE>

なお,あくまでも「HTML文書としてコメントアウト」ですから, <!--〜--> です。 /*〜*/ だと,「CSSとしてコメントアウト」になり,宣言がすべて無効になります^^;

コラム:LINK要素とSTYLE要素の使い分け

スタイルシートは一般に独立したファイルとするのですが,STYLE要素を用いればHTML文書内に直接書き込むことも可能です。このふたつはどのように使い分ければ良いのでしょう。

独立したファイルとして作成したスタイルシートは,LINK要素を介して複数のHTML文書から使用できます。しかし,STYLE要素に記述したスタイルシートは,そのHTML文書からしか活用できません。したがって,使いまわしの効くスタイルシートは独立ファイルとし,特定のHTML文書でしか使えないような特殊な指定をしたシートはSTYLE要素に記述するのが賢い使い分けだと考えられます。

4.3.7. 開始タグ中にスタイル宣言を埋め込む

HTML4.0からは,BODY要素に含まれる(SCRIPTとPARAMを除く)全ての要素にSTYLE属性があり,属性値としてスタイル宣言を記述できます。この方法は,例外的・局所的なスタイル宣言を追加するために利用できます。

<H3 STYLE="color : red; font-size: 1.5em">3.1.1.HTMLに関して</H3>
<H4 STYLE="text-align: center">/HTMLとは/</H4>
<P>HTML(hypertext markup langauge)とは,…</P>