CSSセレクタ, Sass (SCSS) ネスト

(2017.6.24) 最近の状況に更新. Sassを追加。

CSSセレクタについて。

2017.6現在の仕様の最新版は, CSS Snapshot 2017 W3C Working Group Note, 31 January 2017

そこからいろいろな仕様が参照されている。CSSセレクタについては、Selectors Level 3 が CSS 2.1のセクション5を丸ごと置き換えている。

一方, CSS 2.2は、2016年4月で更新が止まっており、やる気がない。

ロジックで言えば Level 3だけを見ればいいんだろうけど、まずはCSS 2.1を押さえておく。

CSS構文: パタンに注目

仕様を読んでいても、例示ばかりで、技術的にはっきりしない。技術文書らしからぬ書き方。構文で確認していく。

構文上 ruleset がパタンと指示内容の組み合わせ。パタンはセレクタを組み合わせたもの。

セレクタを','で区切るのが、一番優先順位が低い.

ruleset
: selector [ ',' S* selector ]*
'{' S* declaration? [ ';' S* declaration? ]* '}' S*

次いで, E F, E + FE > F が同一順位.

selector
: simple_selector [ combinator selector | S+ [ combinator? selector ]? ]?
simple_selector
: element_name [ HASH | class | attrib | pseudo ]*
| [ HASH | class | attrib | pseudo ]+
combinator
: '+' S* | '>' S*

要素名は, こうなっている。

element_name
: IDENT | '*'

属性のほうは, 次のようになる。simple_selector を再掲。複数の条件を連ねるのは、論理積 (AND) になる。構文上は IDセレクタを複数書けることになっているが、意味ない.

simple_selector
: element_name [ HASH | class | attrib | pseudo ]*
| [ HASH | class | attrib | pseudo ]+
HASH
: '#' {nmchar}+
class
: '.' IDENT
attrib
: '[' S* IDENT S* [ [ '=' | "~=" | "|=" ] S*
[ IDENT | STRING ] S* ]? ']'
pseudo
: ':' [ IDENT | IDENT '(' S* [IDENT S*]? ')' ]

複数のセレクタで同じルールを共有

','で区切って複数のセレクタを並べられる。CSSだと構文の優先順位が一番低く, セレクタを全部並べる必要がある。Sassで展開する.

Sass
CSS
  1. .myblock {
  2. p, ul {
  3. background-color:green;
  4. }
  5. }
CSS
(output)
CSS
  1. .myblock p, .myblock ul { background-color: green; }

要素を選択する

ユニバーサルセレクタ, 型セレクタ

パターン例 意味
* いかなる要素にもマッチする。
E いかなるE要素にもマッチする。

ユニバーサルセレクタは, 文書ツリー内のすべての要素にマッチする。simple_selector の唯一の構成要素でない場合, '*' を省略できる。ANDなんだから当然といえば当然。

  • *.warning.warning は等価.
  • *#myid#myid は等価.

子孫、子、隣接(兄弟)セレクタ

パターン例 意味
E F E要素の子孫のF要素にマッチ。
E > F E要素の子であるF要素にマッチ.
E + F 隣接兄弟セレクタ。隣接セレクタとも。Matches any F element immediately preceded by a sibling element E.

子孫セレクタが記号を使わずに空白で表現しているので, .class1.class2 みたいなセレクタにうっかり空白を挿入すると, 意味が変わってしまう.

'*' はユニバーサルセレクタで、演算子ではない。次のように書くと、孫以上という限定になる。

div * p

次は、p は liの子孫、li は ol の子, ol は div の子孫、を全部満たすp要素にマッチする.

div ol > li p

隣接兄弟セレクタE + Fは、同じ親を持ち, かつE の直後 (直下ではない.) にFがくる場合の, 要素F にマッチする.「直後」というのは、非要素ノード(テキストノードやコメントなど)は無視する。要素だけを見る。

隣接セレクタと子孫 (子でも) セレクタを組み合わせることもできる。パッと見、何にマッチするか分かりにくいが。

次の CSS片は, e4要素にマッチする。

e1 e2 + e3 e4 { color:blue; }
HTML
[POPUP]
  1. <e1>AAA
  2. <eX>XXX
  3. <e2>AAA</e2>
  4. <e3>AAA
  5. <e4>MATCH!</e4>
  6. </e3>
  7. </eX>
  8. </e1>

CSSはカッコなどで優先順位を付けることができない。が、おそらく, 式を展開すれば同じ条件で書き直せるはず。

e1 + (e2 e3) => e2 e1 + e3

Sassで書く

Sassで書くと、親子関係は, 二つの書き方がある.

Sass
CSS
  1. h1 {
  2. // 書き方1
  3. + p { // 隣接セレクタ
  4. background-color:#f00;
  5. }
  6. > em { // 子セレクタ
  7. color:blue;
  8. }
  9. }
  10. // 書き方2
  11. h1 + ul {
  12. font-size:2em;
  13. color:green;
  14. }
  15. p > em {
  16. color:red;
  17. }
CSS
(output)
CSS
  1. h1 + p { background-color: #f00; }
  2. h1 > em { color: blue; }
  3. h1 + ul { font-size: 2em; color: green; }
  4. p > em { color: red; }

'&' を使えば、単なるネストでない書き方もできる。

Sass
CSS
  1. #myid {
  2. background-color:#f00;
  3. // 先祖をブロック内で条件にできる.
  4. body.cls1 & {
  5. color:#00f;
  6. }
  7. }
CSS
(output)
CSS
  1. #myid { background-color: #f00; }
  2. body.cls1 #myid { color: #00f; }

属性セレクタ, IDセレクタ

属性セレクタは, 複数の条件を連ねて, AND で限定できる。条件の順序はマッチするかには影響しない。

パターン例 意味
E[foo] "foo"属性を持つE要素にマッチ。属性値は問わない。
E[foo="warning"] "foo"属性の属性値が厳密に"warning"と一致するE要素にマッチ。
E[foo~="warning"] "foo"属性の属性値が空白区切りのリストであって、その一つが"warning"である, E要素とマッチ。
E[lang|="en"] "lang"属性値がハイフン区切りの文字列で、最初のハイフンより左の文字列が"en" である、要素Eにマッチ。~= と違って, 最初の区切りまでの文字列しか見ない。
DIV.warning HTMLでは DIV[class~="warning"] と同じ。XML では、適用ルールを定める、何らかの外部の仕様で決める?
E#myid IDセレクタ。HTMLでは, "id" 属性値が "myid" である要素Eにマッチ。XMLではスキーマによる。が、スキーマ付きのXMLなど滅多にないので、実用ではない。

#p123[id=p123] は同じではない. 意味が同じでも、IDセレクタのほうが優先される. 何でそんなことになっているのか?

Sassで書く

複数のクラスを持つ要素、は '&' を使えばいい。&.cls2 &.cls3 とすると, 子孫セレクタになるのに注意。

Sass
CSS
  1. .cls1 {
  2. background-color:#f00;
  3. &.cls2.cls3 {
  4. color:blue;
  5. }
  6. &.cls4 {
  7. color:orange;
  8. &.cls5 { // .cls1.cls4.cls5
  9. color:green;
  10. }
  11. }
  12. }
CSS
(output)
CSS
  1. .cls1 { background-color: #f00; }
  2. .cls1.cls2.cls3 { color: blue; }
  3. .cls1.cls4 { color: orange; }
  4. .cls1.cls4.cls5 { color: green; }

擬似要素, 擬似クラス

構文は同じだが, 適用される優先順位は, (属性セレクタ, 擬似クラス pseudo-class) のほうが (要素名, 擬似要素 pseudo-element) より上.

擬似クラス

パターン例 意味
E:first-child 要素Eが親の最初の子であるとき、要素Eにマッチ。テキスト・空白などはスキップされる。要素だけを見て、最初の子.
E:link
E:visited
Matches element E if E is the source anchor of a hyperlink of which the target is not yet visited (:link) or already visited (:visited).
E:active
E:hover
E:focus
Matches E during certain user actions.
E:lang(c) Matches element of type E if it is in (human) language c (the document language specifies how language is determined).

擬似要素

  • :first-line
  • :first-letter
  • :before & :after

Sassで書く

Sass
CSS
  1. div {
  2. &:hover {
  3. color:#ff0;
  4. }
  5. :visited { // こちらは div の子孫
  6. color:#00f;
  7. }
  8. }
CSS
(output)
CSS
  1. div:hover { color: #ff0; }
  2. div :visited { color: #00f; }

外部リンク

ご存知、ないのですか?CSSの優先順位
1) style属性値, 2) idセレクタ, 3) 属性セレクタ, 擬似クラス, 4) 要素, 擬似要素、の順で, 優先順位が決まる。
Sass チートシート - Qoosky
書き方例