本業を離れて 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 上での要素の親子関係に言及することになる、ということです。
備忘録終わりです。