解 説

:nth-child() 擬似クラスについて

:nth-child() 擬似クラスの仕様として、W3CのRecommendation仕様書(日本語訳)には以下のように記されています。

6.6.5.2. :nth-child() 擬似クラス

:nth-child(an+b) 擬似クラスは、文書ツリーにおいて、ある要素の子で、その前に an+b-1 個 (n は正の整数もしくは0) の兄弟を持つ状態を表す。a と b が正の数である場合、擬似クラスは要素の子を a 個ずつのグループに分け (最後のグループは余りを持つ)、それぞれのグループから b 番目の要素を選択する。この擬似クラスによりたとえば、表において行ごとを選択することや、4つの段落をひとつのグループとし、グループ内の段落それぞれに異なる色を与えることなどができる。a と b の値は整数 (正、負、もしくは0) でなければならない。最初の子要素のインデックスは1となる。

日本語訳を読んでもなんだかよくわかりません。
簡単に説明すると次のようになります。

E:nth-child(n)は、疑似クラスのひとつです。
n番目の子となるE要素にスタイルを適用する際に使用します。

:nth-child() の簡単な例

:nth-child() の簡単なサンプル
これは2番目のliに赤のボーダーをつけます。

HTMLコード

CSSコード

次のようなHTML構造だと少し戸惑います。どの文字に赤いボーダーが入るでしょうか?
簡単なサンプルで勉強した場合は、eeeeeと答えてしまいがちですが、実はcccccに赤いボーダーがつきます。
:nth-child() の間違いやすいサンプル
HTMLコード

CSSコード

この状態がW3Cの仕様書に書かれている次の部分にあたります。

擬似クラスは、文書ツリーにおいて、ある要素の子で、その前に an+b-1 個 (n は正の整数もしくは0) の兄弟を持つ状態を表す。

「ある要素」はdivです。その子要素が h1, h2, p にあたります。
an+b-1 個 は()の中の3です。
つまり、p:nth-child(3)のことを意味します。
最初の子要素のインデックスは1ですから、最初から3番目のp要素cccccでマッチするわけです。
もう少し詳しく書くなら「ある要素の中にいる兄弟要素の3番目の兄弟でしかもp要素のもの」この条件に合う要素がマッチすることになるのです。
兄弟間にどんな要素があっても関係ないのがnth-child()の特徴です。さらに、もし3番目にp要素がなければマッチは起こらずにボーダーは適用されません。

それでは、CSSの「p:nth-child(3)」の設定はそのままで、HTMLを以下のように変更すると赤いボーダーはどこにつくでしょうか?
サンプル
HTMLコード

これも上の例と同様に考えます。この場合は「ある要素の子」が外側のdivの子要素であり、入れ子状態のdiv要素にもあてはまります。
つまり入れ子状態ができるに従って「ある要素の子」は複数登場してしまうことになるのです。
このような入れ子状態の場合はp:nth-child(3)に複数マッチすることが考えられます。

結果としてはcccccとgggggggに赤いボーダーがつきます。
入れ子状態になる構造の場合はセレクターをしっかりと考えてないと予期せぬ結果が起こることになります。

全称セレクタを活用した方法

次に変わったセレクタの指定方法をみてみましょう。
疑似クラスのコロンの前に半角英数のスペースをひとつ入れています。

セレクタがdivの後に半角スペースを一つ入れてから:nth-child(3)の記述をしています。
どのような結果になるか少し考えてみてください。

サンプル
HTMLコード

CSSコード

そもそもこの例ではdivに兄弟要素はないし、これはボーダーが付かないと考えてしまいます。
けれども答えはサンプルのようにcccccに赤いボーダーがつきます。

さて、この挙動ですが、CSSのセレクタの設定にポイントがあります。
divと:nth-child(3)の間に半角スペースが入っています。ココの半角スペースがポイントです。

ここの半角スペースはアスタリスク(*)、つまり全称セレクタが省略されていると認識されます。
つまり「 div *:nth-child(3) 」と同等に意味になります。

そのため、div要素の子孫要素すべての要素の中で3番目の要素という解釈になるわけです。
その結果3番目の要素がどんなタグでもマッチすることになります。
サンプル

*教科書で使用している「HTML&CSS標準デザイン講座」、またその新版の本でも「nth-child()」の説明が全てこの記述になっています。おそらく独学の方にとっては混乱のもとになると思われます。半角スペースを使ったdiv :nth-child(3)の意味がきちんと説明されていませんので、誤解を生みやすくなっています。注意してください。

:nth-child(an+b)の使い方

:nth-child(an+b)のan+bを使用してみましょう。
:nth-child(n)として()の中をnとすると0から1ずつ数字が入りセレクタで指定した要素の数全てがマッチします。
サンプル
HTMLコード

CSSコード

nの使い方は以上のようになります。これをうまく利用するとさまざまな要素とマッチングができます。
例えば2nとすれば2の倍数とマッチング(偶数)、3nとすれば3の倍数とマッチングします。

偶数奇数

偶数は :nth-child(2n)
偶数サンプル
奇数は :nth-child(2n+1)
奇数サンプル
で表されます。nは0か正の整数です。つまり0,1,2,3,4,5,6,・・・・となります。
偶数、奇数を指定する場合はキーワードも用意されています。
偶数は :nth-child(even)
evenサンプル
奇数は :nth-child(odd)

oddサンプル

:nth-child(an+b)のb値を使ってみる

an+bのb値を設定するとbの値以上にマッチングします。
サンプル
HTMLコード

CSSコード

-an+bとして-aの値を設定するとbの値以下にマッチングします。
:nth-child(-an+b)
サンプル

nth-child