CSS擬似クラス・擬似要素入門
::before・:hover・:nth-childの使い方
CSSの擬似クラスと擬似要素を基礎から解説。:hover、:nth-child、::before、::afterの使い方から、:has()などのモダンCSSまでカバーします。
こんな人向けの記事です
- CSS擬似クラスと擬似要素の違いを理解したい
- ::beforeや::afterの実践的な使い方を知りたい
- :nth-childや:has()を活用したい
Step 1擬似クラスとは
擬似クラスは、要素の状態に応じてスタイルを適用するセレクタです。コロン1つ(:)で記述します。HTMLを変更せずに、ユーザーの操作や要素の位置に応じたスタイルを定義できます。
| 擬似クラス | 対象となる状態 |
|---|---|
:hover | マウスカーソルが乗っている |
:focus | フォーカスされている(クリックやTab移動) |
:active | クリック中(マウスを押している間) |
:visited | 訪問済みのリンク |
:link | 未訪問のリンク |
:focus-visible | キーボード操作でフォーカスされた時のみ |
HTML
<button class="btn">ホバー & クリックしてみてください</button>
CSS
.btn {
display: inline-block;
padding: 12px 32px;
background: #3498db;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
transition: background 0.3s, transform 0.2s;
}
/* マウスを乗せた時 */
.btn:hover {
background: #2980b9;
transform: translateY(-2px);
}
/* クリック中 */
.btn:active {
background: #1c6ea4;
transform: translateY(0);
}
:focus と :focus-visible の違い
HTML
<input type="text" class="input" placeholder="クリックしてフォーカス">
CSS
.input {
padding: 10px 16px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 16px;
outline: none;
transition: border-color 0.3s, box-shadow 0.3s;
}
/* フォーカス時にボーダーとシャドウを変更 */
.input:focus {
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
}
:focus と :focus-visible の使い分け
:focus はクリックでもTabキーでもフォーカス時に適用されます。:focus-visible はキーボード操作でフォーカスした時のみ適用されるため、マウスユーザーには不要なアウトラインを非表示にできます。
Step 2構造擬似クラス
構造擬似クラスは、要素のDOM上の位置(何番目の子要素か)に応じてスタイルを適用します。
| 擬似クラス | 対象 |
|---|---|
:first-child | 最初の子要素 |
:last-child | 最後の子要素 |
:nth-child(n) | n番目の子要素 |
:nth-child(odd) | 奇数番目の子要素 |
:nth-child(even) | 偶数番目の子要素 |
:nth-last-child(n) | 後ろからn番目 |
:only-child | 唯一の子要素 |
:empty | 子要素を持たない空の要素 |
- 1番目(:first-child → 赤太字)
- 2番目(:nth-child(even) → 背景グレー)
- 3番目
- 4番目(:nth-child(even) → 背景グレー)
- 5番目(:last-child → 青太字・ボーダーなし)
HTML
<ul class="list">
<li>1番目</li>
<li>2番目</li>
<li>3番目</li>
<li>4番目</li>
<li>5番目</li>
</ul>
CSS
.list {
list-style: none;
padding: 0;
}
.list li {
padding: 10px 16px;
border-bottom: 1px solid #eee;
}
/* 最初の要素 */
.list li:first-child {
color: #e74c3c;
font-weight: bold;
}
/* 最後の要素:ボーダーなし */
.list li:last-child {
border-bottom: none;
color: #3498db;
font-weight: bold;
}
/* 偶数番目に背景色 */
.list li:nth-child(even) {
background: #f8f9fa;
}
:nth-child() の高度な使い方
CSS
/* 3番目の要素 */
li:nth-child(3) { color: red; }
/* 3の倍数の要素(3, 6, 9...) */
li:nth-child(3n) { background: #eee; }
/* 3番目以降(3, 4, 5...) */
li:nth-child(n+3) { opacity: 0.7; }
/* 最初の3つだけ(1, 2, 3) */
li:nth-child(-n+3) { font-weight: bold; }
/* 偶数番目 */
li:nth-child(even) { background: #f5f5f5; }
/* ↑ これは li:nth-child(2n) と同じ */
Step 3フォーム擬似クラス
フォーム要素の状態に応じてスタイルを変えるための擬似クラスです。バリデーションのフィードバックに特に便利です。
| 擬似クラス | 対象 |
|---|---|
:checked | チェックされたcheckbox / radio |
:disabled | 無効化された要素 |
:enabled | 有効な要素 |
:required | required属性のある要素 |
:optional | required属性のない要素 |
:valid | バリデーションが有効な要素 |
:invalid | バリデーションが無効な要素 |
:placeholder-shown | プレースホルダーが表示されている |
HTML
<div class="form-group">
<label>メールアドレス(required)</label>
<input type="email" required placeholder="example@mail.com">
</div>
<div class="form-group">
<label>無効化されたフィールド</label>
<input type="text" disabled value="編集できません">
</div>
<div class="form-group">
<label>
<input type="checkbox">
チェックしてみてください
</label>
</div>
CSS
input {
padding: 8px 12px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 15px;
outline: none;
transition: border-color 0.3s;
}
/* バリデーションOK → 緑ボーダー */
input:valid {
border-color: #2ecc71;
}
/* バリデーションNG → 赤ボーダー */
input:invalid {
border-color: #e74c3c;
}
/* 無効化 → グレー背景 */
input:disabled {
background: #f5f5f5;
color: #999;
cursor: not-allowed;
}
:valid と :invalid の注意点
:valid / :invalid はページ読み込み時から適用されるため、ユーザーが何も入力していない状態でも赤枠が出ることがあります。:user-invalid(新しい擬似クラス)を使うと、ユーザーが操作した後にのみ適用されます。
Step 4擬似要素とは
擬似要素は、要素の一部分や仮想的なコンテンツにスタイルを適用します。コロン2つ(::)で記述します。HTMLを追加せずに装飾用のコンテンツを挿入できるのが最大の特徴です。
| 擬似要素 | 役割 |
|---|---|
::before | 要素の内容の前にコンテンツを挿入 |
::after | 要素の内容の後にコンテンツを挿入 |
::first-line | 最初の行にスタイルを適用 |
::first-letter | 最初の文字にスタイルを適用 |
::placeholder | inputのプレースホルダーテキスト |
::selection | テキスト選択時のスタイル |
擬似クラスと擬似要素の違い
擬似クラス(:)は要素の「状態」を指定する(:hover, :first-childなど)。擬似要素(::)は要素の「一部分」や「仮想コンテンツ」を指定する(::before, ::afterなど)。
コロンの数で区別します。
HTML
<p><span class="required-label">お名前</span></p>
<p><a href="#" class="link-external">外部リンクの例</a></p>
<div class="quote">CSSは奥が深い。擬似要素を使いこなせば、HTMLを汚さずに装飾できる。</div>
CSS
/* 必須マークを ::after で追加 */
.required-label::after {
content: " *";
color: #e74c3c;
font-weight: bold;
}
/* 外部リンクに矢印アイコンを ::before で追加 */
.link-external::before {
content: "97 ";
}
/* 引用符を ::before で追加 */
.quote {
position: relative;
padding: 16px 20px 16px 40px;
background: #f8f9fa;
border-left: 4px solid #3498db;
border-radius: 4px;
font-style: italic;
}
.quote::before {
content: "C";
position: absolute;
left: 10px;
top: 5px;
font-size: 36px;
color: #3498db;
}
Step 5擬似要素の実践的な活用
カスタムリストマーカー
- HTMLの変更不要で装飾できる
- contentプロパティで文字を挿入
- positionで自由に配置できる
HTML
<ul class="check-list">
<li>HTMLの変更不要で装飾できる</li>
<li>contentプロパティで文字を挿入</li>
<li>positionで自由に配置できる</li>
</ul>
CSS
.check-list {
list-style: none;
padding: 0;
}
.check-list li {
position: relative;
padding: 8px 0 8px 28px;
}
/* チェックマークをリストマーカーとして挿入 */
.check-list li::before {
content: "¹3";
position: absolute;
left: 0;
color: #2ecc71;
font-weight: bold;
font-size: 16px;
}
見出しに装飾ラインを追加
装飾された見出し
見出しの下にグラデーションラインが付きます。
HTML
<h3 class="decorated-heading">装飾された見出し</h3>
CSS
.decorated-heading {
position: relative;
font-size: 20px;
padding-bottom: 10px;
margin-bottom: 16px;
}
/* 下線を ::after で追加 */
.decorated-heading::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 50px;
height: 3px;
background: linear-gradient(to right, #3498db, #2ecc71);
border-radius: 2px;
}
ツールチップ
ホバーしてください
HTML
<span class="tooltip" data-tip="これがツールチップです">
ホバーしてください
</span>
CSS
.tooltip {
position: relative;
display: inline-block;
padding: 8px 20px;
background: #3498db;
color: white;
border-radius: 6px;
cursor: pointer;
}
/* data-tip属性の値をツールチップとして表示 */
.tooltip::after {
content: attr(data-tip);
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 6px 12px;
border-radius: 4px;
font-size: 13px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}
.tooltip:hover::after {
opacity: 1;
}
Step 6モダンCSS — :is(), :where(), :has()
比較的新しい擬似クラスで、セレクタの記述を大幅に簡潔にできます。主要ブラウザで対応済みです。
:is() — セレクタのグループ化
:is() は複数のセレクタをまとめて記述できます。詳細度は引数の中で最も高いものが採用されます。
h3見出し
h4見出し
h5見出し
全ての見出しに同じスタイルが適用されています
CSS
/* :is() を使わない場合 */
.container h3,
.container h4,
.container h5 {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 4px;
}
/* :is() を使う場合 — 同じ結果 */
.container :is(h3, h4, h5) {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 4px;
}
:where() — 詳細度ゼロのグループ化
:where() は :is() と同じ機能ですが、詳細度が常に0になります。上書きしやすいデフォルトスタイルの定義に最適です。
CSS
/* :where() は詳細度 0 → 後から上書きしやすい */
:where(.card, .panel, .box) {
padding: 16px;
border: 1px solid #ddd;
border-radius: 8px;
}
/* クラスセレクタ1つで上書きできる */
.card {
border-color: #3498db; /* 簡単に上書き */
}
:has() — 親セレクタ(革命的)
:has() は「特定の子要素を持つ親」を選択できます。CSSで長年待ち望まれていた機能です。
画像を含むカード → 青ボーダー・背景色あり
テキストのみのカード → デフォルトスタイル
HTML
<!-- 画像を含むカード -->
<div class="card">
<img src="photo.jpg" alt="sample">
<p>画像を含むカード</p>
</div>
<!-- テキストのみのカード -->
<div class="card">
<p>テキストのみのカード</p>
</div>
CSS
.card {
border: 2px solid #ddd;
border-radius: 8px;
padding: 16px;
}
/* imgを子に持つ .card だけにスタイル適用 */
.card:has(img) {
border-color: #3498db;
background: #f0f8ff;
}
:has() の実践的な使い方
CSS
/* チェックされたcheckboxを持つラベルのスタイルを変更 */
label:has(input:checked) {
color: #2ecc71;
font-weight: bold;
}
/* フォーカスされたinputを持つフォームグループ */
.form-group:has(input:focus) {
background: #f0f8ff;
}
/* 空でないセクションだけ表示 */
section:has(> *) {
display: block;
}
/* 隣接する要素にも影響(+ と組み合わせ) */
h2:has(+ p) {
margin-bottom: 8px;
}
ブラウザ対応状況(2025年現在)
:is() と :where() は全モダンブラウザで対応済み。:has() は Chrome 105+, Safari 15.4+, Firefox 121+ で対応。IE は非対応ですが、モダンブラウザでは問題なく使えます。
まとめ
- 擬似クラス(:)は要素の状態を指定 —
:hover,:focus,:nth-child() - 擬似要素(::)は仮想コンテンツを挿入 —
::before,::after - ::before / ::after には必ず
contentプロパティが必要 - :nth-child() は
odd,even,3n,n+3など柔軟な指定が可能 - :has() はCSSだけで「親セレクタ」を実現する革命的な擬似クラス
- :is() / :where() でセレクタをグループ化し、コードを簡潔に