CSS セレクタの構文について

(更新

本業を離れて CSS に深入りすることをお許しください。(^^)

CSS のセレクタを読んでいると、

div.foo#bar:first-child * p, a { ... }

みたいな表記に当たることがあり、プログラマの端くれである私は、構文木がどうなっているのか混乱します。書籍にバッカス・ナウア記法を持ち出せとは言いませんが、なかなか明解な説明を見つけることができませんでした。

しかしさすがは w3.org。同サイトにはこの明確な説明があります。勉強(備忘録)のためにまとめてみました。構文の外側から行きます。(CCS 2.1 ベースです。誤りがあったら御指摘頂けると幸いです。)

グループ化された selector(s)

まず最初に { } の左に現れるものが(仕様書には名称が無いようですが)、selector のグループです。一つ以上の selector が “,” (カンマ)で区切られます。全ての selector に対して、宣言(declaration)が対等に適用されます。

selector-A, selector-B

selector

ある selector は、1つ以上の simple selector を combinator で繋ぎ合わせたものです。combinator とは、空白, “>”, “+” のいずれかです。例えば、次のようなもの(各行)が selector です。

div.foo#bar * p  // 3つの simple selector("div.foo#bar", "*", "p") が空白で繋がれている
span.foo + a     // 2つの simple selector が "+" で繋がれている

simple selector

ある simple selector は、一つの「type selector あるいは universal selector」の後ろに、ゼロ個以上の attribute selector, ID selector, pseudo-class が任意の順序で現れるものです。例えば、次のようなもの(各行)が simple selector です。

div.foo#bar      // type selector "div" の後に、attribute selector と ID selector が一つずつ現れるもの
*                // universal selector のみ
p                // type selector のみ
a:hover          // type selector の後に、pseudo-class が一つ現れるもの

なお、universal selector の後ろに attribute selector, ID selector, pseudo-class などが一つ以上現れる場合 “*” を省略できます。次のような例(各行)です。

.foo#bar         // *.foo#bar と同義
#bar             // *#bar と同義

まとめ

簡単にまとめると、セレクタでは “,” がもっとも結合優先度が低く、次が空白, “>”, “+” で、結合優先度が一番高いのは “.”, “#”, “[]”, “:” などということになります。つまり、むやみに空白を挟んでしまうと、そこは combinator として解釈され、XHTML 上での要素の親子関係に言及することになる、ということです。

備忘録終わりです。