CSSの擬似クラスについて自分の知識があまりにも不足していたお話。

今回は普段お世話になっているCSSについて復習も兼ねて勉強し直してみました。
というのも最近CSSの勉強を怠っていたこともあり、便利な擬似クラスがあることを改めて知る機会がありました。
なので今回はいろんな擬似クラスについて復習と使い方等を紹介できたらと思います。

前提として記事投稿時の情報になりますので、随時更新していければと思いますが、ご容赦ください。

##擬似クラスって？
セレクターに付与することで選択した要素に対して特定の状態を指定することができます。
例えば「:hover」

```css
button:hover {
  color: red;
}
```

とするとポインターが当たったbuttonの文字色が赤色に変化します。
その他だと「:visited」や「:checked」などは目にしたことも多いと思います。
あとよく使うものとして「:before」や「:after」もありますよね。
clearfixもその一つですね！

##便利な擬似クラス
恥ずかしながら知らない擬似クラスや使ったことのないものがたくさんありました。
しかし、あまりにも数が多いので今回は「普段よく使うけど実はもっと良い書き方がある！」というものに絞って紹介したいと思います。

###:first-of-type

私はいつも一番目の要素に適応させたい場合は「:first-child」を利用しておりました。

```css
.hoge .paragraph:first-child {
  color: #fff;
}
```
この指定の仕方は「hogeの一番目の要素」かつ「.paragraph」であればclassが適応されます。
なので下記のようなパターンだと文字色に白色が適用されないという現象が起こります。

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="html,result" data-user="tanimotohikari" data-slug-hash="gEYmxB" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="Qiita:CSS">
  <span>See the Pen <a href="https://codepen.io/tanimotohikari/pen/gEYmxB/">
  Qiita:CSS</a> by tanimotohikari (<a href="https://codepen.io/tanimotohikari">@tanimotohikari</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

原因は「:first-child」は親要素を基準に一番目の要素を検索するためです。
今回の場合だと「.hoge」の一番目の要素は「h3タグ」になり、「.paragraph」が付与されていないのでclassが適用されない状態となっています。

しかし、「:first-of-type」を利用するとクラスを判別してくれるため指定した通りにclassが適用されます。
同じように「:last-of-type」や「:nth-of-type(x)」で最後の要素であったり、x番目の要素に対してスタイルを指定することができます。
また下記のように記述することで柔軟なスタイルの指定が可能です。

```css
/* 
▼最初から3番目までの要素 
-0+3 = 3, -1+3 = 2, -2+3 = 1、と計算されます。
*/
.paragraph:nth-of-type(-n+3) {
  clor: #fff;
}

/* 最初の要素以外 */
.paragraph:not(:first-of-type) {
  clor: #fff;
}

/* 最後から数えてn番目 */
.paragraph:nth-last-of-type(n) {
  clor: #fff;
}

/* 最後の要素かつ奇数 */
.paragraph:nth-of-type(odd):last-of-type {
  color: #fff;
}

/* あるクラス名で始まるn番目の要素 */
[class^="paragraph"]:nth-of-type(n) {
  color: #fff;
}
```


##擬似クラス一覧

###リンク関連の擬似クラス
####:link、 :visited、 :hover、 :active
「:active」は他のリンク関連擬似クラスによって上書きされてしまいます。
なので「:link → :visited → :hover → :active」の順番で定義すると良いでしょう。

|擬似クラス |意味|対応状況|
|---|---|---|
|:link   |訪問されていない要素|IE6以外はOK|
|:visited|訪問済みの要素|IE6以外はOK|
|:hover  |カーソルなどが乗った際|IE6以外はOK|
|:active |クリックされてから離されるまで|IE6以外はOK|
※IE6を気にかけている人は少ないと思いますが、念の為。

####:any-link
「:any-link」で指定することによって:link または :visited に該当するすべての要素にスタイルを当てることができるようです。
ただ、まだ実験的な段階らしくほとんどのブラウザで使用できないかつChromeでも「-webkit-」を付与しないといけないので使えるのはまだ先になりそうです。

###順番に関する擬似クラス
上記で紹介した以外の順番に関する擬似クラスを紹介したいと思います。

####:nth-last-child(n)
兄弟要素の中で、後ろから数えて3つおきに要素にスタイルを当てることができます。
最初から後に向けてではなく最後から前に向けて数えるという点を除けば、:nth-child と同じです。

####:only-child
兄弟要素がない要素に対してスタイルを当てることができます。

###form関連の擬似クラス
formに使用できる擬似クラスは様々なものがあります。
初期値として設定できるものやユーザーの操作でformのに変化が起きたときなどです。
これまでJavaScriptを利用してclassを付与、削除していたものでも擬似クラスを使うことによってCSSのみで完結できるものもあるでしょう。
これまで作ったformを見直してみるとソースの記述量が減って保守や運用がしやすくなるかもしれませんので検討してみてください！

####:default
```<button>```、 ```<input type="checkbox">```、 ```<input type="radio">```、 ```<option>``` 要素に使用することができ、例えば、チェックボックスの中で既定値のチェックボックスにスタイルを適用することができます。

####:checked
選択中のラジオボタン、チェックボックス、オプションボタンの要素にスタイルを適用させることができます。
これはみなさんもおなじみかと思われます。

####:focus、 :focus-visible、 :focus-within
ユーザーが要素をクリックやタップ、キーボードの［タブ］キーで選択したりした要素にスタイルを適用させることができます。
「:checked」とならび非常によく使う擬似クラスの一つではないかと思います。
focusには「[:focus-visible](https://caniuse.com/#search=%3Afocus-visible)」や「[:focus-within](https://caniuse.com/#search=%3Afocus-within)」と擬似クラスがありますがFirefoxでしか利用できない、最新のブラウザのみしか対応していない状態のようです。


####:disabled、 :enabled、 :read-only、 :required、 :optional

|擬似クラス |意味|
|---|---|---|
|:disabled  |無効な要素を示す|
|:enabled   |有効な要素（選択、入力などができるもの）|
|:read-only |ユーザーが編集できない要素|
|:read-write|ユーザーが編集できる要素|
|:required  |有効なデータを持っている必要がある要素（入力欄）|
|:optional  |required 属性が設定されていない要素|
|:invalid  |内容の検証に失敗した```<input>``` 要素 や```<form>```要素|
※「:read-write」→ Firefox では接頭辞付きで対応

ブラウザの対応状況としては
「:disabled」と「:enabled」はIE6~8、Firefox2,3、Safari3.1以外はOKとなっております。
「:read-only」はIEとEdge12、「:optional」と「:required」はIE6~9、Firefox2=3.6、Safari3.1-4がサポートされておりませんのでお気をつけください。

####:in-range、:out-of-range
現在の値が min および max 属性による制限範囲内、範囲外である```<input>```要素に対してスタイルを適用させることができます。

####:indeterminate, :placeholder-shown

「:indeterminate」は```<input type="checkbox">```要素で、JavaScript によって indeterminate プロパティが true に設定されている場合や```<input type="radio">```要素で、フォーム内の同じ name値を持つすべてのラジオボタンが未選択である場合、<progress> 要素で、中間状態の場合にスタイルを適応させることができます。

「:placeholder-shown」はプレイスホルダー文字列が表示されている ```<input>``` または```<textarea>```要素にスタイルを適用させることができます。

###その他擬似クラス
####:empty
「:blank」とできることは似ていますが、「:empty」はスペースが含んでいた場合適用されないので場合によって使い分けするのが良いと思われます。
ブラウザの対応状況としてはIE6~8、Firefox2,3、Safari3.1以外はOKとなっておりますので参考にしてください。

####:defined
定義されている全ての要素に適応させます。

###実験的な段階のクラス
まだ実装で使用するにはブラウザの制限がある、まだ使えない擬似クラスをこれからの期待という意味を込めてご紹介したいと思います。

####:is()
セレクターのリストを引数に取り、リスト中のセレクターのうち一つに当てはまる要素をすべてにスタイルを適用させることができます。
たくさんのセレクターをまとめて同じスタイルにしたい時に便利です。
IEでは使えないので注意が必要です。

####:blank
子ノードを全く持たない要素、あるいは空のテキストノードまたは、ホワイトスペースのみを持つテキストノードを持つ要素に対してスタイルを適用させることができます。
Webサイトでテキストが消えても同じ状態を保つためにスタイルを当てる・・・なんてことは少ないと思いますが、インタラクティブなサイトでは用途はありそうなイメージです。
ただ、残念なことに現在対応しているブラウザはないみたいです。

####:has()
```<img>``` を直接子に持つ``` <a>``` 要素のみに一致させることができます。
これまで複雑な指定でスタイルを当てていた箇所も短い記述で表現できそうですね。
ただ、残念なことに現在対応しているブラウザはないみたいです。
 
### 印刷する文書のスタイル
おそらくWeb制作の現場ではほとんど使われることがない擬似クラスだと思います。

```css
/* 印刷文書の最初のページを表します */
@page :first {
  margin: 2in 3in;
}

/* 印刷文書の左側のページすべてを表します */
@page :left {
  margin: 2in 3in;
}

/* 印刷文書の右側のページすべてを表します。 */
@page :right {
  margin: 2in 3in;
}

```


##まとめ
今回は改めて勉強したことでCSSの記述方法にかなり幅を持たせられるのではないかと実感することができました。
ブラウザによっては対応していないものもありますが、状況を見ながら積極的に取り入れてコーディングのスピードやCSSでの表現に磨きをかけていければと思います。
これからも擬似クラスだけでなく様々なCSSのプロパティが追加されていくと思うのでアンテナを張って表現の幅を持たせられるように取り組みたいと思います。