タイトル: 疑似クラス
SEOタイトル: CSS 疑似クラス 完全ガイド(:hover / :focus / :nth-child / :not / :is / :has / :checked)
| この記事の要点 |
|
疑似クラスとは
疑似クラス (pseudo-class) は、要素の状態 (ホバー中 / フォーカス中など) や文書ツリー上の位置 (最初の子 / n 番目) に基づいてスタイルを適用するための CSS セレクタです。HTML マークアップを変更せずに動的なスタイル変化を作れます。
基本構文
セレクタ:疑似クラス {
プロパティ: 値;
}
a:hover {
color: red;
}
input:focus {
outline: 2px solid #4f46e5;
}
li:first-child {
font-weight: bold;
}
コロンは1 つです。コロン 2 つ (::before など) は疑似要素で別物。
状態に関する疑似クラス
| 疑似クラス | 意味 |
|---|---|
:hover | マウスが乗っている |
:focus | フォーカスを持っている |
:focus-visible | キーボード操作でフォーカスを持っている |
:focus-within | 自身または子孫がフォーカスを持っている |
:active | クリック / タップ中 |
:visited | 訪問済みリンク |
:link | 未訪問リンク |
:checked | チェック済みのチェックボックス / ラジオ |
:disabled | 無効化されたフォーム要素 |
:enabled | 有効なフォーム要素 |
:required | 必須入力のフォーム要素 |
:invalid | 不正な値のフォーム要素 |
:valid | 適切な値のフォーム要素 |
:placeholder-shown | プレースホルダ表示中 (未入力) |
/* リンクの状態別スタイル (LVHA 順) */
a:link { color: blue; } /* 未訪問 */
a:visited { color: purple; } /* 訪問済み */
a:hover { color: red; } /* ホバー */
a:active { color: orange; } /* クリック中 */
/* チェックされたチェックボックスの隣のラベル */
input:checked + label {
color: green;
font-weight: bold;
}
/* 未入力のフォーム要素にラベルを下に表示 (CSS のみフロートラベル) */
input:placeholder-shown + label {
transform: translateY(0);
}
位置に関する疑似クラス (構造擬似クラス)
| 疑似クラス | 意味 |
|---|---|
:first-child | 親の最初の子 |
:last-child | 親の最後の子 |
:only-child | 親の唯一の子 |
:nth-child(n) | n 番目の子 |
:nth-last-child(n) | 後ろから n 番目の子 |
:first-of-type | 同じ種類の要素の最初 |
:last-of-type | 同じ種類の要素の最後 |
:nth-of-type(n) | 同じ種類の n 番目 |
:only-of-type | 同じ種類の唯一の要素 |
:empty | 子要素もテキストも持たない |
:root | 文書のルート (通常 html) |
/* テーブルの偶数行 (ゼブラストライプ) */
tr:nth-child(even) {
background: #f5f5f5;
}
/* 1, 4, 7... 3 ずつ */
li:nth-child(3n + 1) {
color: red;
}
/* 最初の段落だけ大きく */
p:first-of-type {
font-size: 1.2em;
}
/* 子要素が 1 個もない要素を隠す */
.message:empty {
display: none;
}
nth-child(n) の式
| 式 | マッチ |
|---|---|
3 | 3 番目 |
odd | 奇数番目 |
even | 偶数番目 |
2n | 2, 4, 6, ... (= even) |
2n + 1 | 1, 3, 5, ... (= odd) |
3n | 3, 6, 9, ... |
n + 3 | 3 番目以降すべて |
-n + 3 | 最初の 3 つ |
否定・論理疑似クラス
:not()
/* .important 以外の li */
li:not(.important) {
color: gray;
}
/* 複数の否定 */
button:not(.primary):not(.danger) {
background: #eee;
}
:is() — セレクタリストの簡潔化
/* 従来 */
h1 .highlight,
h2 .highlight,
h3 .highlight {
color: red;
}
/* :is() を使うと */
:is(h1, h2, h3) .highlight {
color: red;
}
セレクタの詳細度は引数内で最も高いものになります。
:where() — 詳細度ゼロ
:where() は :is() と同じだが詳細度を 0 にカウントするため、デフォルトスタイル定義に最適。
/* 後から簡単に上書き可能なデフォルトスタイル */
:where(article, section) p {
line-height: 1.7;
}
:has() — CSS の親セレクタ
CSS で長年待望されていた「子に〜がある親」を選ぶセレクタ。Chrome / Edge / Safari 対応 (2023〜)、Firefox も 121+ 対応。
/* img を持つ figure */
figure:has(img) {
background: #f0f0f0;
}
/* チェックされた input を持つ label */
label:has(input:checked) {
color: green;
font-weight: bold;
}
/* 子に .error を持つカードを赤枠 */
.card:has(.error) {
border-color: red;
}
/* 直接の子 a がない li を弱表示 */
nav li:not(:has(> a)) {
opacity: 0.5;
}
その他の便利な疑似クラス
| 疑似クラス | 意味 |
|---|---|
:target | URL のフラグメント (#xxx) と一致する id を持つ要素 |
:lang(ja) | 指定言語の要素 |
:dir(rtl) | 右から左に書く言語 |
:default | デフォルト要素 (form の submit ボタンなど) |
:in-range | input の値が範囲内 |
:out-of-range | input の値が範囲外 |
:read-only | 読み取り専用の input |
:read-write | 編集可能な input |
疑似クラスと疑似要素の違い
| 項目 | 疑似クラス | 疑似要素 |
|---|---|---|
| コロン | 1 つ (:hover) | 2 つ (::before) |
| 対象 | 既存の要素の状態 / 位置 | 要素の一部 / 仮想要素 |
| 例 | :hover :nth-child | ::before ::first-line |
FAQ
Q: :hover とタッチデバイスの相性
A: タッチデバイスでは hover が「タップ時の状態」になりがち。@media (hover: hover) でホバー可能なデバイスだけに適用するのがモダン。
Q: :focus と :focus-visible どちらを使う?
A: :focus-visible はキーボード操作時のみ。マウスクリックで outline が出ないので見た目がスッキリ。アクセシビリティとデザインの両立に最適。
Q: :has() の詳細度は?
A: 引数内の最も高い詳細度になる。:has(.btn) は class 1 個分の詳細度。
関連
- 疑似要素 (
::before/::after/::placeholderなど) - CSS セレクタ全般 (要素 / クラス / ID / 属性 / 子孫)