In 'n' Out

知識を取り込み、そして発信する

疑似クラス

疑似クラスとは

擬似クラスは、要素そのものではなく「状態」や「条件」に基づいてスタイルを適用するためのCSSセレクタです。
ユーザー操作、フォームの状態、要素の位置関係など、HTMLだけでは表現できない条件を指定できます。
JavaScriptを使わずにUIの変化を表現できる点が、擬似クラスの大きな特長です。

疑似クラス

まずは疑似クラスにはどのようなものがあるのか一覧表でまとめました。

疑似クラス一覧
疑似クラス主な対象説明
:hover全要素マウスカーソルが乗っている状態
:active全要素要素内容のクリック・押下中の状態
:focusフォーム要素・リンクフォーカスされている状態
:focus-visibleフォーム要素キーボード操作時にフォーカス表示
:visiteda要素訪問済みリンク
:linka要素未訪問リンク
:checkedcheckbox・radioチェックされている状態
:disabledフォーム要素無効化されている状態
:enabledフォーム要素有効な状態
:requiredフォーム要素必須入力項目
:validフォーム要素入力内容が妥当
:invalidフォーム要素入力内容が不正
:first-child全要素親要素の最初の子要素
:last-child全要素親要素の最後の子要素
:nth-child(n)全要素n番目の子要素
:nth-of-type(n)全要素同じ要素型のn番目
:not()全要素指定条件に当てはまらない要素
:only-child全要素親に子が1つだけの場合
:empty全要素中身が空の要素
:roothtmlルート要素
:target全要素URLのアンカーで指定された要素

疑似クラスには多くの種類がありますが、実務で頻繁に使用されるものは限られています。
すべてを覚える必要はなく、UI操作や要素の状態に関わるものを中心に理解していくとよいでしょう。

状態遷移系

リンク要素は、ユーザーの操作や閲覧状況によって状態が変化します。
リンク状態遷移系の疑似クラスは、その状態変化に応じてスタイルを切り替えるための指定方法です。
主にa要素に対して使用され、リンクの見た目や操作感を制御するために欠かせません。

未訪問リンク

:linkはまだ一度も訪問していないリンクに対してスタイルを適用する疑似クラスで、aタグ専用の疑似クラスです。

構文

a:link{
    プロパティ:"値";
}

a要素の中でも、ブラウザの履歴上、未訪問と判定されたリンクのみに一致します。
HTMLやCSSで訪問状態を制御することはできず、判定はブラウザに委ねられます。

コード例

<a href="#link-target1">リンク</a>
a:link{
    color: red;
}

出力例

未訪問の状態ではリンク文字が赤く表示されます。
:linkはa要素全体に指定する場合と挙動がほぼ同じになるため、実際はaにまとめて書かれることが多く、単独で使われる場面は多くありません。 訪問済みと見た目を明確に分けたい場合に限定して使うのが現実的です。

訪問済みリンク

:visitedは一度でも訪問したことのあるリンクに対してスタイルを適用する疑似クラスで、aタグ専用の疑似クラスです。

構文

a:visited{
    プロパティ:"値";
}

:link同様、ブラウザの履歴を元に判定され、ユーザーが過去にアクセスしたURLに対して一致します。
HTMLやCSSで訪問状態を制御することはできず、判定はブラウザに委ねられます。

コード例

<a href="#link-target2">リンク</a>
a:visited{
    color: green;
}

出力例

訪問済みの状態ではリンク文字が緑色で表示されます。
セキュリティ上の理由から、:visited で指定できるプロパティは制限されています。
color など一部の装飾プロパティのみが有効で、レイアウトに影響する指定はできません。
そのため、訪問済みであることが分かる程度の控えめな装飾に留めるのが基本です。

マウスオーバー

マウスカーソルが要素の上に乗っている状態を表します。

構文

セレクタ:hover{
    プロパティ:値;
}

ユーザー操作に直接反応する疑似クラスで、リンクが操作可能であることを視覚的に示す役割を持ちます。

コード例

<div>
    <h4>hoverはaタグ専用ではありません</h4>
    <a href="#link-target3">リンク</a>
</div>
h4:hover{
    font-weight: normal;
    color: red;
}
        
a:hover{
    color: red;
}

出力例

マウスを乗せるとCSSで指定した状態に変化します。
:hoverは最も使用頻度が高い疑似クラスですが、スマートフォンではhover状態が存在しない点に注意が必要です。
そのため、hoverのみで操作性を伝える設計は避け、focusなど他の状態と併用することが重要になります。

押下

クリックして押している間の状態を表します。

構文

セレクタ:active{
    プロパティ:値;
}

マウスボタンを押している間だけ一時的に適用され、クリックが完了すると解除されます。

コード例

<div>
    <a href="#link-target4">リンク</a>
    <button>長押しすると文字が太くなります。</button>
</div>
a{
    display: block;
}

a:active{
    border: 1px solid #ff0000;
}

button:active{
    font-weight: bold;
}

出力例

クリック中のみリンクが薄く表示されます。
:active の効果時間は非常に短いため、単体で使われることは少なく、hover の補助として使われることが一般的です。
押した感覚を与えるための補助的な表現と考えると理解しやすいでしょう。

フォーカス

キーボード操作などで要素が選択されている状態を表します。

構文

セレクタ:focus{
    プロパティ:値;
}

Tabキー操作やクリックによって要素が操作対象になったとき、その要素に適用されます。
マウスを使わない操作を支える重要な疑似クラスです。

コード例

<div>
    <button>クリック後にフォーカス状態になります</button>
    <button>クリック後にフォーカス状態になります</button>
</div>
button{
    display: block;
}
button:focus{
    font-weight: bold;
}

出力例

:focusは、キーボード操作などで要素が操作対象になっていることを示す疑似クラスですが、出力例ではマウス操作のみ行ってください。
button の文字が太くなるスタイルが適用されます。 Tabキーによる移動時にも適用されるため、ユーザーが現在どの要素を操作しているのかを視覚的に把握するために重要な役割を持ちます。 なお、フォーカスの移動自体を制御するものではありません。

リンク系疑似クラスは、指定順によって挙動が変わるため、:link、:visited、:hover、:active、:focusの順番で書くのが一般的です。 この順番をLVHAFと呼び、順番を守ることで、意図しない上書きを防ぐことができます。

並び順・条件指定疑似クラス

並び順・条件指定の疑似クラスは、HTML要素の順番や条件に応じてスタイルを適用するための仕組みです。
classやidを追加せず、「何番目か」「特定条件に当てはまるか」といった情報をもとに指定できるため、HTML構造を活かしたCSS設計が可能になります。

最初の子要素

親要素の中で最初の子要素に一致します。

構文

セレクタ:first-child{
    プロパティ:値;
}

指定したセレクタが、親要素の最初の子要素である場合に適用されます。

コード例

<ul>
    <li=>項目1</li>
    <li=>項目2</li>
    <li=>項目3</li>
</ul>
<div>
    <p>段落1</p>
    <p>段落2</p>
    <p>段落3</p>
</div>
<div>
    <h4>タイトル</h4>
    <p>段落1</p>
    <p>段落2</p>
    <p>段落3</p>
</div>
li:first-child{
    color: red;
}

p:first-child{
    color: blue;
}

出力例

  • 項目1
  • 項目2
  • 項目3

段落1

段落2

段落3

タイトル

段落1

段落2

段落3

1つ目はliではなく、最初の子要素がliであるかが判定基準となります。
2つ目は最初の子要素がpなので、スタイルが適用されますが、3つ目は最初の子要素がh4なのでスタイルが適用されません。
このようにテキストノードや別要素があると一致しない場合があるため、構造が決まっていないと有効になりません。

最後の子要素

親要素の中で最後の子要素に一致します。

構文

セレクタ:last-child{
    プロパティ:値;
}

指定したセレクタが、親要素の最後の子要素である場合に適用されます。

コード例

<ul>
    <li>項目1</li>
    <li>項目2</li>
    <li>項目3</li>
</ul>
<div>
    <p>段落1</p>
    <p>段落2</p>
    <p>段落3</p>
</div>
<div>
    <p>段落1</p>
    <p>段落2</p>
    <p>段落3</p>
    <span>最後の文字列</span>
</div>
li:last-child{
    color: red;
}

p:last-child{
    color: blue;
}

出力例

  • 項目1
  • 項目2
  • 項目3

段落1

段落2

段落3

タイトル

段落1

段落2

段落3

最後の文字列

:first-childの逆で、同様1つ目は最後の子要素がliであるかが判定基準となります。
2つ目は最後の子要素がpなので、スタイルが適用されますが、3つ目は最初の子要素がspanなのでスタイルが適用されません。
このようにテキストノードや別要素があると一致しない場合があるため、構造が決まっていないと有効になりません。

n番目の子要素

親要素の中でn番目の子要素に一致します。

構文

セレクタ:nth-child(n){
    プロパティ:値;
}

nには数値や計算式を指定できます。

コード例

<ul class="n-number">
    <li>項目1</li>
    <li>項目2</li>
    <li>項目3</li>
    <li>項目4</li>
    <li>項目5</li>
    <li>項目6</li>
</ul>
<ul class="n-3number">
    <li>項目1</li>
    <li>項目2</li>
    <li>項目3</li>
    <li>項目4</li>
    <li>項目5</li>
    <li>項目6</li>
</ul>
<ul class="n-odd">
    <li>項目1</li>
    <li>項目2</li>
    <li>項目3</li>
    <li>項目4</li>
    <li>項目5</li>
    <li>項目6</li>
</ul>
.n-number li:nth-child(4){
    color: red;
}

.n-3number li:nth-child(3n){
    color: blue;
}

.n-odd li:nth-child(odd){
    color: green;
}

出力例

  • 項目1
  • 項目2
  • 項目3
  • 項目4
  • 項目5
  • 項目6
  • 項目1
  • 項目2
  • 項目3
  • 項目4
  • 項目5
  • 項目6
  • 項目1
  • 項目2
  • 項目3
  • 項目4
  • 項目5
  • 項目6

:nth-childはカッコ内に数値を指定することで、スタイルが適用されます。
1つ目は4のみなので、liの4番目にスタイルが適用され、2つ目は3nなので、3の倍数である3番目と6番目にスタイルが適用されます。
3つ目はoddを指定して奇数番目のみにスタイルが適用されます。
ちなみにevenを指定すると偶数番目のみにスタイルが適用されます。
ただし、要素の種類を問わず、順番のみで判定するため、他の要素が混ざると意図しない結果になるため、構造を理解した上で使用すれば指定が楽にはなります。

n番目の同要素

同じ要素タイプの中でn番目に一致します。

構文

セレクタ:nth-of-type(n){
    プロパティ:値;
}

nには数値や計算式を指定できます。

コード例

<div>
    <p>1番目の段落</p>
    <p>2番目の段落</p>
    <span>段落以外の要素</span>
    <p>3番目の段落</p>
    <p>4番目の段落</p>
</div>
p:nth-of-type(4){
    color: red;
}

出力例

1番目の段落

2番目の段落

段落以外の要素

3番目の段落

4番目の段落

:nth-of-typeは:nth-childとは異なり、要素が間に挟まれていても指定通りに4番目のpにスタイルが適用されます。
そのため、指定した要素で数えてくれるため構造に強い点が挙げられます。
また、nth-childと同様に3の倍数なら3n、evenやoddも使用できるため、nth-childよりも使える場面は多いです。

条件以外の要素

指定した条件以外の要素に一致します。

構文

セレクタ:not(条件){
    プロパティ:値;
}

否定する条件をまとめて指定できます。

コード例

<div class="not">
    <p>1番目の段落</li>
    <p>2番目の段落</li>
    <span>段落以外の要素</span>
    <p>3番目の段落</li>
    <p>4番目の段落</li>
</div>
<div class="wrong-not">
    <p>1番目の段落</li>
    <p>2番目の段落</li>
    <span>段落以外の要素</span>
    <p>3番目の段落</li>
    <p>4番目の段落</li>
</div>
div{
    border: 1px solid #000000;
}

.not :not(p){
    color: red;
}
        
.wrong-not:not(p){
    color: green;
}

出力例

1番目の段落

2番目の段落

段落以外の要素

3番目の段落

4番目の段落

1番目の段落

2番目の段落

段落以外の要素

3番目の段落

4番目の段落

:notの正しい出力例と間違った出力例です。
1つ目はnotクラスの付いたdivの直下p以外の要素という意味です。
2つ目は同じように指定しているように見えますが、pではないwrong-notクラスがついたdivという意味で、div要素の中にあるものすべての文字が緑色のスタイルが適用されてしまいます。
このように意味が違うとまったく異なる結果が表示されるので注意が必要です。