【CSS】いつのまにか :nth-child() が拡張されていた件

## はじめに

みなさんは、`:nth-child()` はよく使っていますか？
`:nth-child()` を知らずにWEBサイトを作っている方は少ないと思いますが、`:nth-child()`の書き方が拡張されていることを知らない方は多いのではないでしょうか？

この記事では、そんな `:nth-child()` を改めて紹介し、拡張された `:nth-child()` について解説しようと思います。

## `:nth-child()` の基本

`:nth-child()`は、同じ親要素にある兄弟関係の全ての要素の中で何番目になるのかを指定するものです。

```html
<!--タグに指定する p:nth-child() -->
<div>
    <p>1番目</p>
    <a>2番目</a> 
    <p>3番目</p>
    <p>４番目</p>
</div>
```

このようなDOMのときに、`p:nth-child()` でスタイルを指定すると、要素のカウントは上記のようになります。
ただ、2番目は `<a>` になっているので、スタイルは反映されません


### 使い方
#### 最初の要素を指定する
```css
p:first-child {
  /*スタイルが入る*/
}
```

#### 最後の要素を指定する
```css
p:last-child {
  /*スタイルが入る*/
}
```

#### 最初からx番目の要素を指定する
```css
p:nth-child(3) {
  /*スタイルが入る*/
}
```

#### 最後からx番目の要素を指定する
```css
p:nth-last-child(3) {
  /*スタイルが入る*/
}
```

#### x番目の要素から最後の要素までを指定する
```css
p:nth-child(n+3) {
  /*スタイルが入る*/
}
```

#### 最初からx番目の要素までを指定する
```css
p:nth-child(-n+3) {
  /*スタイルが入る*/
}
```

#### 最後からx番目の要素から最初の要素までを指定する
```css
p:nth-last-child(n+3) {
  /*スタイルが入る*/
}
```

#### 最後からx番目の要素から最後の要素までを指定する
```css
p:nth-last-child(-n+3) {
  /*スタイルが入る*/
}
```

#### xの倍数番目の要素を指定する
```css
p:nth-child(3n) {
  /*スタイルが入る*/
}
```

#### xの倍数番目のy個となりの要素
```css
p:nth-child(3n+2) {
  /*スタイルが入る*/
}
```

#### 兄弟要素が自分1個だけの時
```css
p:only-child {
  /*スタイルが入る*/
}
```

## 拡張された `:nth-child() of S` 構文

`:nth-child() of S` 構文は、基本的な指定から、さらにフィルターをかけることができます。

例えば、以下のようなDOMがあるとします。

```html
<p>1番目</p>
<a class="paragraph">2番目</a> 
<p class="paragraph">3番目</p>
<p>4番目</p>
<p>5番目</p>
<p class="paragraph">6番目</p>
```

上記のようなDOMに以下のようなスタイルを指定します。

```css
p:nth-child(even of .paragraph) {

}
```

上記のようにスタイルを指定すると、**pタグの兄弟要素の中で、`paragraph`というclassが付いている要素の偶数番目の要素**を変更することができます。

つまり、pタグの兄弟要素の中だと、3番目の要素のスタイルが変わるということです。

### サンプル　①
上記の例を実際に再現してみると↓このようになります。

<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="vYooQKx" data-pen-title=":nth-child() of S - sample 1" data-editable="true" data-user="sp_degu" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/vYooQKx">
  :nth-child() of S - sample 1</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


### サンプル　②
<p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="ZEggqrj" data-pen-title="requestAnimationFrame() - 一時停止・再生" data-editable="true" data-user="sp_degu" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/ZEggqrj">
  requestAnimationFrame() - 一時停止・再生</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

上記の左側の例だと、`nth-child(even)`でスタイル指定しているので、偶数番目の要素の背景が変わっています。
記の右側の例だと、`p:nth-child(even of :not([hidden]))`でスタイルを指定しているので、`hidden`属性が書かれていない要素の偶数番目の要素の背景が変わっています。

## まとめ
この記事では、`:nth-child()`を使って、フィルタリンできる `:nth-child() of S` 構文について説明しました。

`:nth-child()`の順番の数え方で、痒い所に手が届いていなかった部分もできるようになったようです。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510