仕様書の概要
用語など
CSSスタイルシートのパースとトークン化
ユーザー・エージェントはCSSスタイルシートを読み込むとCSSOMツリーを構築するためにCSSパーサーによるパースが行われます。
CSSパーサーはパースに先だってユニコード符号位置の集合体として入力されたCSSスタイルシートを“トークン化(Tokenization)”します。トークン化では連続するユニコード符号位置を組み合わせて意味を持った1個の単位であるトークンを生成し、CSSスタイルシートをトークンの集合に変換します。
トークン化の後、CSSパーサーは“パース(Parsing)”によって以下のアイテムから構成されるツリーを構築して出力します。
- “@ルール(At-rule)”
- 名前とコンポーネント値のリスト、任意でそれに続く“{}”単純ブロックから構成されます。
- “適合ルール(Qualified rule)”
- コンポーネント値のリストとそれに続く“{}”単純ブロックから構成されます。
- ほとんどの適合ルールはスタイル・ルールですが、そうでない適合ルールもあります。例えば、“@keyframes”ルールの中にある記述されるキーフレームの指定は適合ルールですが、スタイル・ルールではありません。
- “宣言(Declaration)”
- 名前とコンポーネント値のリストである値、既定では未設定の重要度フラグ(“!important”)から構成される。
- 宣言はさらに“プロパティ(Properties)”と“ディスクリプタ(Descriptors)”に分類されます。
- “コンポーネント値(Component Value)”
- 温存トークン、関数、単純ブロックのいずれかです。
- “温存トークン(Preserved Tokens)”
- トークン化によって生成されたトークンで、“<function-token>”、“<{-token>”、“<(-token>”、“<[-token>”以外のもの。
- “関数(Function)”
- 名前(“<function-token>”)とコンポーネント値のリストである値から構成されます。
- “単純ブロック(Simple block)”
- “<{-token>”、“<(-token>”、“<[-token>”のいずれかとコンポーネント値のリストから構成されます。
CSSパーサーによる出力は基本的なCSSの構文によって構築され、個々のアイテムの有効性は考慮されません。
CSSパーサーは入力されたCSSスタイルシートを最後に“CSSStyleSheet”オブジェクトとして出力します。
パースの事前処理
ユーザー・エージェントはネットワークやローカルのディスクからCSSスタイルシートを単なる数値の並びであるバイトの集合体として受け取り、それを決められた文字エンコーディングの方法によって解釈して符号位置に変換します。
最初にユーザー・エージェントは“BOMスニッフィング(BOM sniffing)”によって最初の3バイトもしくは2バイトである“BOM(Byte Order Mark)”を読み取り、エンコーディングの方法を調べます。
BOM | エンコーディング |
---|---|
0xEF 0xBB 0xBF | UTF-8 |
0xFE 0xFF | UTF-16BE |
0xFF 0xFE | UTF-16LE |
BOMスニッフィングによってエンコーディングがわからない場合には、以下の方法で算出した“代替エンコーディング(Fallback Encoding)”を使用します。
- HTTPや同等の他のプロトコルがエンコーディングを定義していれば、そのエンコーディングを取得して代替のエンコーディングにします。
- そうでなければ、最初の1024バイトを読み取り、“@charset "…"”として解釈される16進数のコード(“40 63 68 61 72 73 65 74 20 22 … 22 3B”)で始まるのであれば、示されたエンコーディングを取得して代替のエンコーディングにします。取得したエンコーディングが“utf-16be”か“utf-16le”の場合は“utf-8”とします。
- そうでなければ、CSSの適用先の文書の記述言語が定義する方法(HTMLの“link”要素の“charset”属性など)があれば示されたエンコーディングを取得して代替のエンコーディングにします。
- そうでなければ、“utf-8”を代替のエンコーディングにします。
文字エンコーディングによって符号位置に置き換えられた後、CSSスタイルシートはCSSパーサーに入力されますが、その前に一部の文字は以下のように置き換えられます。
- 復帰(CR、U+000D)、改頁(FF、U+000C)、もしくは復帰(CR、U+000D)と行送り(LF、U+000A)の組を表す符号位置はそれぞれ1個の行送り(CR、U+000A)を表す符号位置に置き換えられます。
- ヌル(NUL、U+0000)と代用符号位置(U+D800からU+DFFFまで)を表す符号位置はそれぞれ置換文字(U+FFFD、“�”)を表す符号位置に置き換えられます。
トークンの構文
“<ident-token>”
- 最初に任意でハイフンマイナス(U+002D、“-”)
- 続いて以下のいずれかを組み合わせた文字列
- 英字(“a”~“z”と“A”~“Z”)、アンダースコア(U+005F、“_”)、非ASCII文字(U+0080以降)
- エスケープ・シーケンス
- 続いて任意で以下のいずれかを組み合わせた文字列
- 英字(“a”~“z”と“A”~“Z”)、数字(“0”~“9”)、ハイフンマイナス(U+002D、“-”)、アンダースコア(U+005F、“_”)、非ASCII文字(U+0080以降)
- エスケープ・シーケンス
もしくは以下の構文です。
- 最初に2個連続するハイフンマイナス(U+002D、“--”)
- 続いて任意で以下のいずれかを組み合わせた文字列
- 英字(“a”~“z”と“A”~“Z”)、数字(“0”~“9”)、ハイフンマイナス(U+002D、“-”)、アンダースコア(U+005F、“_”)、非ASCII文字(U+0080以降)
- エスケープ・シーケンス
CSSのソースコードのうち“<ident-token>”の構文と同じ構文である部分は“識別子(Identifier)”と呼ばれます。
“<function-token>”
- 最初に“<ident-token>”
- 続いて始め丸括弧(U+0028、“(”)
“<at-keyword-token>”
- 最初にアットマーク(U+0040、“@”)
- 続いて“<ident-token>”
“<hash-token>”
- 最初にハッシュ(U+0023、“#”)
- 続いて以下のいずれかを組み合わせた文字列
- 英字(“a”~“z”と“A”~“Z”)、数字(“0”~“9”)、ハイフンマイナス(U+002D、“-”)、アンダースコア(U+005F、“_”)、非ASCII文字(U+0080以降)
- エスケープ・シーケンス
“<string-token>”
- 最初に二重引用符(U+0022、“"”)
- 続いて以下のいずれかを組み合わせた文字列
- 二重引用符(U+0022、“"”)とリバースソリダス(U+005C、“\”)以外の文字
- エスケープ・シーケンス
- リバースソリダス(U+005C、“\”)に続く改行
- 最後に二重引用符(U+0022、“"”)
もしくは以下の構文です。
- 最初に単一引用符(U+0027、“'”)
- 続いて以下のいずれかを組み合わせた文字列
- 単一引用符(U+0027、“'”)とリバースソリダス(U+005C、“\”)以外の文字
- エスケープ・シーケンス
- リバースソリダス(U+005C、“\”)に続く改行
- 最後に単一引用符(U+0027、“'”)
“<url-token>”
- 最初に“url”と一致する“<ident-token>”
- 続いて始め丸括弧(U+0028、“(”)
- 続いて任意で1個以上のホワイトスペース(“ws*”)
- 続いて以下のいずれかを組み合わせた文字列
- 二重引用符(U+0022、“"”)、単一引用符(U+0027、“'”)、始め丸括弧(U+0028、“(”)、終わり丸括弧(U+0029、“)”)、リバースソリダス(U+005C、“\”)、ホワイトスペース、制御文字以外の文字
- エスケープ・シーケンス
- 続いて任意で1個以上のホワイトスペース(“ws*”)
- 最後に終わり丸括弧(U+0029、“)”)
“<number-token>”
“<number-token>”は以下の構文です。
- 最初に任意で1個のプラス(U+002B、“+”)もしくはハイフンマイナス(U+002D、“-”)
- 続いて以下のいずれか
- 1個以上の数字(“0”~“9”)
- 1個以上の数字(“0”~“9”)に続く1個のフルストップ(U+002B、“.”)、さらにその後に続く1個以上の数字(“0”~“9”)
- 1個のフルストップ(U+002B、“.”)に続く1個以上の数字(“0”~“9”)
- 続いて任意で以下の文字列
- 1個の“e”もしくは“E”
- 続いて任意で1個のプラス(U+002B、“+”)もしくはハイフンマイナス(U+002D、“-”)
- 続いて1個以上の数字(“0”~“9”)
“<dimension-token>”
- 最初に“<number-token>”
- 続いて“<ident-token>”
“<percentage-token>”
- 最初に“<number-token>”
- 続いてパーセント記号(U+0025、“%”)
その他のトークン
コメント
- 最初に“/*”
- 続いて“*/”を含まない任意の文字列
- 最後に“*/”
改行
以下のいずれかを1個。
- “\n”(行送り)
- “\r\n”(復帰+行送り)
- “\r”(復帰)
- “\f”(改頁)
16進数
以下のいずれかを1個。
- 数字(“0”~“9”)
- “a”~“f”
- “A”~“F”
エスケープシーケンス
- 最初にリバースソリダス(U+005C、“\”)
- 続いて以下のいずれか
- 改行と16進数以外の文字
- 1個から6個の16進数とそれに続く任意のホワイトスペース
“<whitespace-token>”
以下のいずれかをそれぞれ0個以上。
- 半角スペース(U+0020)
- “\t”(タブ文字)
- 改行
“ws*”
“<whitespace-token>”を0個以上。
“<CDO-token>”
1個の“<!--”。
“<CDC-token>”
1個の“-->”。
“<colon-token>”
1個のコロン(U+003A、“:”)。
“<semicolon-token>”
1個のセミコロン(U+003B、“;”)。
“<comma-token>”
1個のコンマ(U+002C、“,”)。
“<[-token>”
1個の始め角括弧(U+005B、“[”)。
“<]-token>”
1個の終わり角括弧(U+005D、“]”)。
“<{-token>”
1個の始め波括弧(U+007B、“{”)。
“<}-token>”
1個の終わり波括弧(U+007D、“}”)。
“<(-token>”
1個の始め丸括弧(U+0028、“:”)。
“<)-token>”
1個の終わり丸括弧(U+0029、“:”)。
“<delim-token>”
トークン化で他のトークンに含まれない以下の文字とその他の符号位置。
- ハッシュ(U+0023、“#”)
- プラス(U+002B、“+”)
- ハイフンマイナス(U+002D、“-”)
- フルストップ(U+002B、“.”)
- 小なり記号(U+003C、“<”)
- アットマーク(U+0040、“#”)
- リバースソリダス(U+005C、“\”)
“<bad-string-token>”、“<bad-url-token>”
トークン化の過程で正常に“<string-token>”や“<url-token>”にトークン化されない時に生成されます。
CSSの構文
スタイルシート
以下のいずれかをそれぞれ0個以上。
- “<CDO-token>”
- “<CDC-token>”
- “<whitespace-token>”
- 適合ルール
- @ルール
ルール・リスト
以下のいずれかをそれぞれ0個以上。
- “<whitespace-token>”
- 適合ルール
- @ルール
@ルール
- 最初に“<at-keyword-token>”
- 続いて0個以上のコンポーネント値
- 続いて以下のいずれか
- “{}”ブロック
- セミコロン(“;”)
適合ルール
- 最初に0個以上のコンポーネント値
- 続いて“{}”ブロック
宣言リスト
- 最初に0個以上のホワイトスペース(“ws*”)
- 続いて0個以上の宣言
- 続いて0個以上のセミコロン(“;”)に続く宣言リスト
もしくは以下の構文です。
- 最初に0個以上のホワイトスペース(“ws*”)
- 続いて1個の@ルール
- 続いて1個の宣言リスト
宣言
- 最初に“<ident-token>”
- 続いて0個以上のホワイトスペース(“ws*”)
- 続いてコロン(“:”)
- 続いて0個以上のコンポーネント値
- 続いて任意で1個の“!important”
“!important”
- 最初に感嘆符(“!”)
- 続いて0個以上のホワイトスペース(“ws*”)
- 続いて“important”と一致する“<ident-token>”
- 続いて0個以上のホワイトスペース(“ws*”)
コンポーネント値
以下のいずれかを1個。
- 温存トークン
- “{}”ブロック
- “()”ブロック
- “[]”ブロック
- 関数ブロック
“{}”ブロック
- 最初に始め波括弧(“{”)
- 続いてコンポーネント値
- 最後に終わり波括弧(“}”)
“()”ブロック
- 最初に始め丸括弧(“(”)
- 続いてコンポーネント値
- 最後に終わり丸括弧(“)”)
“[]”ブロック
- 最初に始め角括弧(“[”)
- 続いてコンポーネント値
- 最後に終わり角括弧(“]”)
関数ブロック
- 最初に“<function-token>”
- 続いて1個以上のコンポーネント値
- 最後に終わり丸括弧(“)”)
CSSルールや値の文法の定義
CSSの仕様書の中では、CSSルールの文法を定義するために“<”と“>”で囲んだ表記を使用しています。これは他所で定義されている定義への参照で、例えば、構文の中で“<rule-list>”が使用されている箇所では“<rule-list>”の構文を当てはめることができます。
いくつかのトークンは引用符をつけずにそのまま記されます。
- “<ident-token>”
- “auto”などはそのままのトークンの値として示されます。
- “<at-keyword-token>”
- “@”に続くトークンの値として示されます。
- “<function-token>”
- 関数の名前に続く“(”として示されます。
- “<colon-token>”、“<comma-token>”、“<semicolon-token>”、“<(-token>”、“<)-token>”、“<{-token>”、“<}-token>”
- それぞれ“:”、“,”、“;”、“(”、“)”、“{”、“}”として示されます。
トークンはトークンの値がそれぞれの文法で定義された値と一致する場合に一致します。一部の例外を除いてトークンの一致は英字の大文字と小文字を区別しません。
“<delim-token>”は単一引用符(“'”)で囲んで示されます。
“<whitespace-token>”はCSSルールの文法の中では示されませんが、一部の例外を除き、トークンの前、トークンの後、もしくは2個のトークンの間に自由に挿入することが許されています。
ブロック・コンテンツ
- “<declaration-list>”
- 宣言のリストを表し、ブロックの唯一の値でなければなりません。ブロックのコンテンツは宣言リストをトークン化する仕組みを使用してパースされます。
- “<declaration-list>”として有効なプロパティ、ディスクリプタ、@ルールはそれぞれの仕様書で定義されます。
- ディスクリプタにつけられた“!important”は無効です。プロパティの場合はカスケードされるプロパティであれば“!important”はそのカスケード・オリジンで通常の効果を持ち、カスケードされなければ“!important”がつけられた宣言は無効です。
- “<rule-list>”
- ルールのリストを表し、ブロックの唯一の値でなければなりません。ブロックのコンテンツはルールをトークン化する仕組みを使用してパースされます。
- “<rule-list>”として有効なルールはそれぞれの仕様書で定義され、無効なルールは無視されます。
- “<stylesheet>”
- “<rule-list>”とほぼ同じですが、別途制限がなければどのようなルールも許容します。
自由文法のコンテンツ
- “<declaration-value>”
- 1個以上のどのようなトークンの組み合わせとも一致します。
- ただし、“<bad-string-token>”、“<bad-url-token>”、ペアになるトークンがない“<)-token>”と“<]-token>”、“<}-token>”、スタイルシートの最上位にある“<semicolon-token>”、値が“!”である“<delim-token>”のいずれかを含む場合は除きます。
- “<any-value>”
- “<declaration-value>”とほぼ同じですが、スタイルシートの最上位にある“<semicolon-token>”、値が“!”である“<delim-token>”を含むことができます。
スタイル・ルール
“スタイル・ルール(Style Rule)”は適合ルールの一種で、セレクタ(セレクタ・リスト)とそれに続くプロパティによる宣言のリストを内包するブロックからなります。スタイル・ルールはCSS2では“スタイル・セット(Style Set)”と呼ばれます。
スタイル・ルールの先頭にあるコンポーネント値が“<selector-list>”としてパースできない場合にはスタイル・ルール全体が無効となります。
スタイル・ルールのブロックの中は宣言のリストとしてパースされます。別途定義されていない限り、@ルールはスタイル・ルールのブロックの中では無効であり、無視されます。また、不明なCSSプロパティやプロパティのものとして定義されている値の構文と一致しない値による宣言は無効であり、無視されます。スタイル・ルールのブロックの中にある個々のコンテンツの有効・無効はスタイル・ルール全体の有効・無効には影響しません。
プロパティ名は別途定義されていない限り英字の大文字と小文字の区別はありません。
CSSスタイルシートの最上位にある適合ルールはすべてスタイル・ルールです。最上位以外のコンテキスト(@ルールのブロックの中など)にある適合ルールはそのコンテキストの定義によってスタイル・ルールであったり、そうでなかったりします。
エスケープ
どのような文字でも“エスケープ・シーケンス(Escape Sequence)”を使用して“エスケープ(Escaping)”することで識別子や引用符囲みの文字列の中に含むことができます。
エスケープ・シーケンスは以下の2通りがあります。
- リバースソリダス(“\”)に続く16進数(“0”~“9”、
“A”~“F”、 と改行文字以外の文字“a”~“f”) - エスケープ・シーケンスはリバースソリダスの後に記述された文字に置き換えられます。
- リバースソリダス(“\”)に続く1個から6個の16進数(“0”~“9”、
“A”~“F”、 “a”~“f”) - エスケープ・シーケンスは示された16進数によってユニコード符号位置が表される文字に置き換えられます。
- エスケープ・シーケンスの直後にホワイトスペースを挿入してエスケープ・シーケンスと直後に続く他の文字を区別することができます。