CSSの疑似クラスとは?:hover・:focus・:nth-childの書き方と使い方を初心者向けに解説

ボタンにマウスポインターを重ねたときだけ色を変えたい。入力欄を選んだ位置を、枠線で分かりやすくしたい。こうした操作に応じた見た目をCSSで作るときに使うのが、疑似クラスです。

疑似クラスには、操作の状態を選ぶ:hover・:focusと、同じ親の中に並ぶ要素の順番を選ぶ:nth-child()などがあります。まず「いつ変えるか」と「何番目を変えるか」を分けると、目的に合う書き方を選びやすくなります。

HTMLのclassとCSSの基本形を学び始めた方に向けて、練習用HTMLの用意から3つの疑似クラスの書き方、効かないときの確認順まで解説します。パソコンのテキストエディターとブラウザーを使い、ボタン・入力欄・一覧を一つずつ試して、ポインターやTabキーで変化を確かめることが目標です。

この記事で分かること
  • CSSの疑似クラスが選ぶ「状態」と「位置」
  • :hover・:focus・:nth-child()の違い
  • HTML・CSSを書く場所と、保存後の確認方法
  • odd・even・An+Bを使った並び順の指定
  • 疑似クラスが効かないときの確認順
目次

CSSの疑似クラスとは

疑似クラスとは、選択した要素が特定の状態や位置にあるときだけ、CSSを適用するためのキーワードです。セレクターの後ろへ半角のコロン:と疑似クラス名を書きます。MDNの「疑似クラス」では、ユーザー操作、文書内の位置、入力内容の状態など、多くの疑似クラスを確認できます。

たとえば、.button:hoverは「buttonというclass名を持ち、ポインターが重なっている要素」を選びます。.buttonという対象に、:hoverという状態の条件を追加していると考えると分かりやすいでしょう。

疑似クラスの基本的な書き方

基本形は「セレクター+コロン+疑似クラス名」です。

セレクター:疑似クラス {
  プロパティ: 値;
}

次のコードは、.buttonへポインターが重なったときだけ背景色を変えます。

.button:hover {
  background-color: #3d433b;
}

:nth-child()のように丸括弧があるものは、関数形式の疑似クラスです。丸括弧の中へ、何番目を選ぶかという条件を書きます。

.item:nth-child(2) {
  background-color: #f5f6f2;
}

同じ親の直下に並ぶ要素を「兄弟要素」と呼びます。この例では、その中で2番目にあり、かつitemというclass名を持つ要素が対象です。セレクター、class、idの違いがまだ曖昧な方は、「CSSセレクタとは?」を先に確認してください。

練習用HTMLを用意して、保存後に確認する

STEP
練習用のファイルを保存する

練習用のフォルダーを新しく作り、テキストエディターに次のコードをすべて貼り付けます。ファイル名をindex.html、文字コードをUTF-8にして、そのフォルダーへ保存してください。末尾が.html.txtになっていないことも確認します。

<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>疑似クラスの練習</title>
  <style>
    .button {
      padding: 12px 20px;
      color: #ffffff;
      background-color: #536048;
    }
    .button:hover {
      background-color: #3d433b;
    }
  </style>
</head>
<body>
  <button class="button" type="button">試してみる</button>
</body>
</html>
STEP
ブラウザーで開いて変化を確かめる

保存したindex.htmlをブラウザーで開きます。「試してみる」ボタンが表示され、ポインターを重ねると濃い色になり、外すと元の色へ戻れば、この例の確認は完了です。

STEP
各節の例に置き換えて保存する

各節のHTML例は<body>の内側へ、CSS例は<style>の内側へ書きます。節を切り替えるときは前の例を置き換え、同じclass名のCSSが残らないようにしてください。変更のたびにファイルを保存し、ブラウザーを再読み込みします。

最初からやり直すときは、STEP 1のコード全体へ戻して保存・再読み込みしてください。すでに外部CSSファイルを読み込んでいる場合は、そのファイルへCSSを書いても構いません。

classセレクター・疑似要素との違い

classセレクターは、HTMLのclass属性へ自分で付けた名前をピリオド.で選びます。疑似クラスは、ブラウザーが判断できる状態や位置をコロン:で条件にします。

疑似要素は、要素の一部や仮想的な部分を選ぶ仕組みです。基本的にコロンを2つ重ねた::beforeや::first-lineのように書きます。MDNの「疑似要素」でも、疑似クラスとの構文の違いを確認できます。

.buttonはclass名、.button:hoverは状態、.button::beforeは仮想の部分を選ぶ。

.buttonはHTMLへ付けた名前、:hoverは要素の状態、::beforeは要素の前に作る仮想的な部分を選びます。半角コロン1つは疑似クラス、基本的に2つは疑似要素と覚えると、最初の書き分けがしやすくなります。

:hover・:focus・:nth-child()の違い

3つの疑似クラスは、何を条件にするかが異なります。

書き方選ぶ条件主な用途
:hoverポインターが上にあるリンク・ボタンの変化
:focusフォーカスされている入力欄・操作位置の表示
:nth-child()兄弟要素の中の位置一覧の特定・交互表示

:hoverと:focusは、ユーザー操作によって変わる状態を選びます。一方、:nth-child()は、同じ親を持つ兄弟要素の並び順を選びます。

:hoverの書き方と使い方

:hoverは、ポインターが要素の上にある状態を選ぶ疑似クラスです。マウス操作では、マウスポインターをボタンやリンクへ重ねたときに一致します。詳しい定義はMDNの「:hover」で確認できます。

ボタンにポインターを重ねたとき色を変える

練習用HTMLの<body>内に、操作を試すためのボタンを書きます。このボタンを押しても、ページの移動や送信は行いません。

<button class="button" type="button">試してみる</button>

通常時の色を指定した後、.button:hoverへ変化後の色を書きます。

.button {
  display: inline-block;
  padding: 12px 20px;
  color: #ffffff;
  background-color: #536048;
}

.button:hover {
  background-color: #3d433b;
}

保存してブラウザーを再読み込みし、ボタンへポインターを重ねます。背景が濃い色になり、外すと元の色へ戻れば成功です。:hoverはリンク、画像、カードなどにも使えます。

タッチ画面でのhoverの注意点

タッチ画面では、マウスと同じ意味の「ポインターを重ね続ける」操作がない場合があります。端末によってはタップ後に:hoverが残ったり、想定したタイミングで一致しなかったりします。

そのため、hoverしないと読めない説明や、hoverしないと押せない操作を作らないことが大切です。重要な文章やボタンは通常時から表示し、:hoverは色や影などの補助的な変化に使いましょう。

発展として、主な入力方法がhoverに対応する場合だけ変化を付けるなら、次のように書けます。先ほどの.button:hoverの規則を、この@media全体へ置き換えてください。元の規則が外側に残ると、条件を付けたつもりでもその規則が適用されます。

@media (hover: hover) {
  .button:hover {
    background-color: #3d433b;
  }
}

@media (hover: hover)は、マウスなど、要素にポインターを重ねられる機器が主な操作方法のときだけ、内側のCSSを適用します。詳しい条件はMDNの「hover」で確認できます。

:focusの書き方と使い方

:focusは、要素がフォーカスを受け取っている状態を選びます。フォーカスとは、キーボード入力や操作の対象として、現在選ばれている状態です。リンクやボタンはTabキーで移動したとき、入力欄はクリックまたはタップしたときなどにフォーカスされます。

入力欄を選んだとき枠線を変える

次のHTMLには、名前を入力する欄があります。

<label for="name">お名前</label>
<input id="name" class="input" type="text">

.input:focusへ枠線と輪郭を指定します。

.input {
  border: 2px solid #7a8e6d;
}

.input:focus {
  border-color: #536048;
  outline: 3px solid #536048;
  outline-offset: 2px;
}

保存・再読み込み後、入力欄をクリックするかTabキーで選びます。外側に濃い緑の輪郭が現れ、文字を入力できれば確認完了です。Shift+Tabで前の操作対象へ戻れます。:focusの対象と例はMDNの「:focus」で確認できます。

hoverはポインターが上にある状態、focusは現在の入力・操作対象。両方に一致する場合もある。

:hoverは主にポインターの位置、:focusは現在の操作対象を示します。マウスだけでなくキーボードでも操作できるリンクやボタンでは、両方の状態を用意すると変化を見つけやすくなります。

フォーカスの輪郭と見やすさ

ブラウザーは、キーボード操作などで現在位置を示す必要があると判断すると、フォーカス中の要素へ輪郭などを表示します。デザインを整える目的でoutline: noneだけを書くと、キーボードで現在位置を確認できなくなるおそれがあります。

フォーカスの輪郭を消すなら、同等以上に見分けやすい代替表示を必ず用意するようにします。輪郭、枠線、背景色のどれか一つだけに頼らず、周囲とのコントラストや表示位置も確認してください。

:focus-visibleで必要なときに輪郭を表示する

:focus-visibleは、要素がフォーカスされ、ブラウザーがフォーカス表示を必要と判断したときに一致する疑似クラスです。多くの場合、Tabキーで移動したときに一致し、マウスでクリックしたときは一致しないことがあります。

この例は入力欄ではなく、最初の「試してみる」ボタンで確かめます。練習ファイルをSTEP 1のコード全体へ戻してから、<style>の閉じタグの直前へ次のCSSを追加してください。

.button:focus-visible {
  outline: 3px solid #536048;
  outline-offset: 3px;
}

保存して再読み込みし、Tabキーでボタンを選びます。ボタンの外側に輪郭が出れば確認は完了です。マウスでクリックしたときに同じ輪郭が出なくても、それだけで誤りとは限りません。

:focus-visibleは「キーボード専用」という固定条件ではありません。入力方法や要素の種類などをもとに、ブラウザーが表示の必要性を判断します。詳しい考え方はMDNの「:focus-visible」で確認できます。

HOAI Point

:hoverと:focus-visibleを対で考えると、ポインターでもキーボードでも変化を確認できます。色だけで区別せず、輪郭や下線など形の変化も組み合わせましょう。

:nth-child()の書き方と使い方

:nth-child()は、同じ親を持つ兄弟要素の中で、指定した位置にある要素を選びます。数え始めは0ではなく1です。丸括弧の中へ数字、odd、even、An+B形式の式を書きます。

数字で特定の1件を選ぶ

次のHTMLには3つの項目があります。

<ul class="list">
  <li class="item">基本</li>
  <li class="item">応用</li>
  <li class="item">実践</li>
</ul>

2番目の項目だけを選ぶ場合は、:nth-child(2)と書きます。

.item:nth-child(2) {
  font-weight: 700;
}

このコードでは「応用」だけが太字になります。:nth-child()は兄弟要素を1番目から数えることを覚えておきましょう。

oddとevenで奇数・偶数を選ぶ

oddは奇数番目、evenは偶数番目を選びます。一覧の行を交互に塗り分けるときに便利です。

.item:nth-child(odd) {
  background-color: #fcfcfa;
}

.item:nth-child(even) {
  background-color: #f2d89c;
}

このCSSを試すと、3件のうち2番目の「応用」に淡い黄色の背景が付きます。項目を増やせば、1・3・5番目はodd、2・4・6番目はevenの対象になります。class名を交互に付け直す必要はありません。

An+Bで一定の間隔や範囲を選ぶ

An+Bでは、nに0、1、2…を順に入れて、当てはまる位置を求めます。たとえば3n+1は、nが0なら1番目、1なら4番目、2なら7番目です。-n+3は3、2、1となるため、1〜3番目が選ばれます。0番目はないため、その先は選ばれません。

  • 3n:3・6・9番目のように3件ごと
  • 3n+1:1・4・7番目のように3件ごとの先頭
  • -n+3:1〜3番目まで
.item:nth-child(3n) {
  border-bottom: 3px solid #c28a3d;
}

前の3件の一覧で試すと、3番目の「実践」に下線のような下側の枠線が付きます。nが0のときは3 × 0 = 0ですが、0番目の要素はないため選ばれません。項目を増やすと、3・6・9番目が対象になります。

:nth-child()が数える兄弟要素

.card:nth-child(2)のように書くと、.cardだけを先に数えるわけではありません。同じ親の直下にある要素をすべて数え、2番目の要素が.cardにも一致するときに選びます。HTMLを読みやすくするための空白や改行、コメントは、この順番に含めません。

<section class="cards">
  <h2>おすすめ記事</h2>
  <article class="card">CSS入門</article>
  <article class="card">HTML入門</article>
</section>
.card:nth-child(2) {
  border: 3px solid #c28a3d;
}

保存・再読み込み後、「CSS入門」に金色の枠線が付けば成功です。.cardsの1番目の子はh2、2番目の子は最初のarticleなので、最初のカードが選ばれます。ここではborderへ太さ・種類・色をまとめて指定しているため、枠線がない初期状態からでも変化を確認できます。

.cardsの子をh2、CSS入門のarticle、HTML入門のarticleの順に数えると、.card:nth-child(2)はCSS入門を選ぶ。
図中のarticle.cardは、class="card"を持つarticle要素を表します。

「2番目のカード」と「親の2番目の子」は、HTMLの構造によって同じにも別にもなります。期待した要素が選ばれないときは、class名だけでなく親要素の直下に並ぶすべての要素を確認してください。詳しい数え方はMDNの「:nth-child()」で確認できます。

同じ要素名の中で何番目かを条件にしたい場合は、:nth-of-type()が適することもあります。article:nth-of-type(2)は、同じ親の中にあるarticle要素だけを数え、その2番目を選びます。ただし、数えているのはarticleというタグ名で、.cardというclass名だけを数えているわけではありません。

3つの疑似クラスを組み合わせた実践例

個別の例を確認できたら、記事一覧へ組み合わせてみましょう。ここでは見出しを除き、3枚のカードだけを同じ親の中へ並べます。偶数番目のカードの背景を変え、リンクにはポインターとキーボードの両方で分かる変化を付けます。hrefの値は説明用のリンク先です。練習ではクリックやEnterキーで移動せず、色と輪郭の変化を確認します。自分のページで使う場合は実在するURLへ置き換えてください。

<div class="cards">
  <article class="card"><a href="/html/">HTML入門</a></article>
  <article class="card"><a href="/css/">CSS入門</a></article>
  <article class="card"><a href="/layout/">レイアウト入門</a></article>
</div>
.card {
  padding: 20px;
  background-color: #fcfcfa;
  border: 2px solid #7a8e6d;
  border-radius: 12px;
}

.card:nth-child(even) {
  background-color: #f2d89c;
}

.card a {
  color: #3d433b;
  text-decoration: underline;
}

.card a:hover {
  color: #536048;
  text-decoration-thickness: 3px;
}

.card a:focus-visible {
  outline: 3px solid #536048;
  outline-offset: 4px;
}

保存して再読み込みすると、2番目の「CSS入門」のカードに淡い黄色の背景が付きます。リンクにポインターを重ねて文字色と下線の太さを確かめ、次にポインターを外してTabキーでリンクを順に選びます。輪郭が移動すれば、3つの役割を確認できています。

疑似クラスごとに役割を分けている点が重要です。:nth-child(even)はHTMLの並び順、:hoverはポインターの状態、:focus-visibleはフォーカス表示が必要な状態を担当します。カードの背景色・枠線・角丸の基本は、「CSSで背景色・枠線・角丸を設定する方法」で詳しく確認できます。

HOAI Point

通常時の見た目を先に作り、疑似クラスで変化を追加すると、CSSを追いやすくなります。疑似クラスの中へ共通の余白やサイズを重複させず、変化するプロパティだけを書きましょう。

疑似クラスが効かないときの確認順

まずファイルを保存し、表示中のページが編集したHTMLか確かめて再読み込みします。通常時の色や余白も変わらない場合は、疑似クラスより先にCSSの保存先・読み込み先を確認してください。通常時は反映され、条件を付けた部分だけ変わらないときは、まず次の3点を確認します。

  1. コロンが半角の:になっているか
  2. 疑似クラスをセレクターの後ろへ続けて書いているか
  3. class名や要素名がHTMLと一致しているか

続いて、下の小見出しから今の症状に合うものを選びます。スマートフォンのhover、フォーカス、選ばれる順番をそれぞれ確認し、条件が合っているのに変わらない場合は「CSSが上書きされている場合」へ進んでください。

構文、対象、状態または位置、上書きの順で確認すると、原因を切り分けやすくなります。一度に複数の箇所を変えず、一つ修正するたびに保存・再読み込みして結果を確認してください。各例の想定した変化が出れば、その症状の確認は終了です。

:hoverがスマートフォンで想定どおりにならない場合

タッチ操作ではhoverできない、またはタップ後にhover状態が残る場合があります。:hoverがなくても内容と操作が成立する設計にし、必要に応じて@media (hover: hover)の内側へhover用CSSを書きます。タッチ操作では、hoverの色が付くかだけで判断せず、触れる前から必要な情報が見え、リンクやボタンを操作できることを確かめてください。

:focusが効かない場合

まず、対象がTabキーなどで選べる要素か確認します。代表例は、href属性のあるa要素、button要素、input要素です。見た目だけのdiv要素へtabindexを付けて無理に操作対象にするより、リンクならa、ボタンならbuttonのように、用途に合うHTML要素を使いましょう。この記事の入力欄なら、Tabキーで選ぶと外側に濃い緑の輪郭が現れ、文字を入力できれば確認は完了です。:focus-visibleの例はボタンを対象にしているため、HTMLを入力欄のままにしていないかも確認してください。

:nth-child()が1件ずれる場合

対象の親要素を確認し、その直下にある見出し、段落、カードなどを上から1、2、3と数えます。途中に別の要素があると、その要素も位置の計算へ含まれます。数えた位置とclass名の両方が条件に合う要素へ色が付けば確認は完了です。字下げの空白や改行は要素ではないため、数へ含めません。

CSSが上書きされている場合

パソコンのブラウザーで対象要素を右クリックし、「検証」などの項目から開発者ツールを開きます。対象のスタイルを見て、同じプロパティのどの値が有効か、どのCSSファイルから来ているかを確認してください。取り消し線だけで上書きと断定せず、値の誤りや条件に一致していない可能性も調べます。!importantを増やす前に、該当する宣言を一つずつ直しましょう。開発者ツール上だけの変更は再読み込みで消えるため、修正内容を元の練習ファイルへ反映して保存します。再読み込み後も想定した変化が出れば確認は完了です。

よくある質問

基本の例を試した後に迷いやすい、条件の重ね方と数える対象の絞り込みを補足します。

疑似クラスは複数つなげられますか?

つなげられます。たとえば.button:hover:focusは、同じ要素がhoverとfocusの両方に一致するときだけ選びます。ただし、条件が厳しくなるほど一致する場面が減るため、必要な状態だけを組み合わせてください。複数の状態へ同じ見た目を適用したい場合は、.button:hover, .button:focus-visibleのようにセレクターをカンマで並べます。

特定のclassだけを数えて2番目を選べますか?

発展的な書き方として、:nth-child(2 of .card)があります。同じ親の直下にある.cardだけを数えるため、見出しとカードが並ぶ先ほどの例では「HTML入門」を選びます。.card:nth-child(2)との違いに注意してください。対応するブラウザーの範囲は、MDNの「:nth-child()の互換性」で確認できます。

まとめ

CSSの疑似クラスは、要素の状態や文書内の位置を条件にしてスタイルを適用する仕組みです。

  • 疑似クラスはセレクターの後ろへ半角コロン:で書く
  • :hoverはポインターが要素の上にある状態を選ぶ
  • :focusは現在フォーカスされている要素を選ぶ
  • :focus-visibleはブラウザーがフォーカス表示を必要と判断した状態を選ぶ
  • :nth-child()は同じ親を持つ兄弟要素を1番目から数える
  • hoverだけに重要情報を任せず、フォーカスの輪郭を代替なしで消さない
  • 効かないときは、保存・読み込みを確かめてから構文、対象、状態または位置、上書きを確認する

まずは手元のリンクへ:hoverと:focus-visibleを追加し、マウスとTabキーの両方で変化を確認してみてください。次に3件の一覧へ:nth-child(even)を指定すると、状態を選ぶ疑似クラスと、位置を選ぶ疑似クラスの違いを体験できます。

目的別に次の記事を選ぶ

疑似クラスの基本を確認したら、次は書きたいCSSや見た目に合う記事を選びましょう。

要素・class・idを組み合わせて対象を正確に選びたいなら、「CSSセレクタとは?」でセレクターの優先順位と使い分けを確認してください。

ボタンやカードの通常時の背景色・枠線・角丸から整えたいなら、「CSSで背景色・枠線・角丸を設定する方法」で3つのプロパティを確認してください。

この記事を書いた人

横畑デザイン事務所代表。Webデザイナー・プログラミング講師として、WordPressを中心としたWebサイトの制作・運用と個別指導に携わっています。実際の制作や指導で培った知識と経験をもとに、Web制作やAI活用について、初心者が迷わず一歩を踏み出せる情報を分かりやすく発信しています。

目次