はじめに
CSSには一般的なセレクタの指定方法の他にも、特定の状態や位置の要素に指定する擬似クラスや、HTMLを記述しなくても要素を追加できる疑似要素という概念があります。
擬似クラスと疑似要素は、要素にスタイルを適用するためのセレクタの拡張として機能します。
指定した要素のスタイリングだけでなく、要素の状態や位置に基づいてスタイリングができるため、JavaScriptなどを使用せず、簡単にインタラクティブなスタイルの変更を行うことができます。
この記事では、ウェブ制作初心者の方向けに擬似クラス・疑似要素の概要と基本的な使い方について、具体的なコード例や実例を用いて解説します。
この記事の対象者
- ウェブ制作初心者の方
- 「:」で区切られたセレクタの意味が分からない方
- 疑似クラス・疑似要素について知りたい方
この記事の目標
- 疑似クラス・疑似要素の概要について理解する
- 疑似クラス・疑似要素の注意点について理解する
- 基本的な疑似クラス・疑似要素の使い方を知る
擬似クラスについて
擬似クラスは、ユーザーがマウスを要素の上に持ってきたときや要素がフォーカスされたときなど、要素の特定の状態に対してスタイルを適用できます。これにより、ユーザーの操作に応じて要素の外観を変更することができます。
また、特定の位置の要素を指定したり、一部の要素にスタイルを適用させないようにするなど、新たにクラスを追加せずに柔軟な制御を可能にします。
疑似クラスは、通常のセレクタに「:(コロン)」で区切って疑似クラス名を追記することで指定できます。
以下は「hover」という疑似クラスにスタイルを指定した例です。
div:hover {
background-color: blue;
}
一般的によく使われる疑似クラスをリンク関連、位置関連に分けてご紹介します。
リンク関連の疑似クラス
疑似クラスを使用することで、aタグなどのリンク要素に対して,特定の状態に応じてスタイルを適用することができます。
リンク関連でよく使われる基本的な疑似クラスは以下のとおりです。
- link:リンクに適用されます。
- visited:リンク先が訪問済みだった場合に適用されます。
- hover:要素の上にカーソルがある時に適用されます。
- active:要素をクリックした際に適用されます。
それぞれの使い方と注意点について簡単に解説します。
link
link疑似クラスは、その要素がリンクだった場合に適用されます。主にa要素に対して使用されますが、a要素にhref属性が無い場合は適用されません。
a:link {
background-color: red;
}
<a href="#">適用されます。</a>
<a>適用されません。</a>
この例では、2つ目のa要素にはhref属性が記述されていないため:linkのスタイルは適用されません。
visited
visited疑似クラスは、ユーザーがリンク先を訪問済みだった場合に適用されます。:visitedの注意点として、元の要素で指定されていないプロパティは変更することができません。
a:link {
color: red;
background-color: white;
}
a:visited {
color: pink;
background-color: gray; /* 適用される */
border: 1px solid black; /* 適用されない */
}
この例では、a:linkのブロック内でbackground-colorプロパティが指定されているため、a:visitedのbackground-colorは適用されます。
しかし、a:linkにはborderプロパティの指定がないため、a:visitedのborderは適用されません。
hover
hover疑似クラスは、ユーザーの操作によってマウスカーソルが要素と重なった場合に適用されます。
hover時のスタイルを変更することでユーザーは要素がクリックできる状態かを視覚的に判断することができるので、効果的に使用することでユーザー体験の向上になります。
a {
color: red;
background-color: white;
}
a:hover {
color: white;
background-color: red;
}
この例では、a要素に対して文字色を赤、背景色を白を設定しています。
また、a:hoverブロック内の記述により、a要素にマウスカーソルが重なった場合は文字色と背景色が反転します。
a要素を例に挙げていますが、:hoverはa要素以外にも使用できます。
acitive
active疑似クラスは、クリックした時などユーザーによってアクティブ化された要素に適用されます。
アクティブな状態とは、PCでマウス操作している場合はクリックしている状態を指し、長押ししている間はアクティブな状態を保ちます。タッチデバイスではタッチした瞬間や長押しの操作が該当します。
a {
color: red;
background-color: white;
}
a:active {
color: white;
background-color: red;
}
この例では、a要素をクリックした際に一瞬だけ文字色と背景色が反転します。
:activeも:hover同様、a要素以外に使用できます。
これらのリンク関連の疑似要素は、記述する順番に気を付けないと正しく適用されない可能性があります。
以下の順番で記述することで適切にスタイルを反映させることができるので、覚えておくと良いでしょう。
a:link {}
a:visited {}
a:hover {}
a:active {}
位置関連の疑似クラス
疑似クラスを使用することで、要素が特定の位置にあるときにスタイルを適用させることができます。
位置関連でよく使われる基本的な疑似クラスは以下のとおりです。
- first-child:要素の種類を区別せず、一番目の要素に適用されます。
- last-child:要素の種類を区別せず、最後の要素に適用されます。
- nth-child():要素の種類を区別せず、指定した位置の要素に適用されます。
- first-of-type:要素の種類を区別し、一番目の要素に適用されます。
- last-of-type:要素の種類を区別し、最後の要素に適用されます。
- nth-of-type():要素の種類を区別し、指定した位置の要素に適用されます。
これらを使うことで、要素の位置や順序に基づいてスタイルを指定することができるようになります。
first-child, last-child, nth-child()
これらの疑似クラスは、兄弟要素のグループ内を基準にして位置を特定します。
li {
color: black;
}
li:first-child {
color: red;
}
li:last-child {
color: blue;
}
<ul>
<li>li:first-childなので赤文字です。</li>
<li>黒文字</li>
<li>黒文字</li>
<li>黒文字</li>
<li>li:last-childなので青文字です。</li>
</ul>
<ul>
<li>li:first-childなので赤文字です。</li>
<li>黒文字</li>
<li>黒文字</li>
<li>黒文字</li>
<li>li:last-childなので青文字です。</li>
</ul>
li要素はulによってグルーピングされているため、li:first-childやli:last-childのスタイルはそれぞれのul内で作用します。
また、nth-child()を使用することで、任意の位置にある要素を指定できます。
/* 2番目のli */
li:nth-child(2) {
color: red;
}
/* 奇数番目のli */
li:nth-child(odd) {
color: red;
}
/* 偶数番目のli */
li:nth-child(even) {
color: red;
}
これらの疑似要素は入れ子にして使用することもできます。
ただし、クラス名を使用したほうが分かりやすいので通常は使用しません。
li {
color: black;
}
ul:first-child li:nth-child(odd) {
color: red;
}
<!-- 以下はul:first-childなので適用されます -->
<ul>
<li>奇数番目のliなので赤文字です。</li>
<li>黒文字</li>
<li>奇数番目のliなので赤文字です。</li>
<li>黒文字</li>
<li>li:last-childなので青文字です。</li>
</ul>
<!-- 以下はul:first-childではありません -->
<ul>
<li>黒文字</li>
<li>黒文字</li>
<li>黒文字</li>
<li>黒文字</li>
<li>黒文字</li>
</ul>
first-of-type, last-of-type, nth-of-type()
これらの疑似クラスは、兄弟要素のグループ内を基準にし、要素の種類を区別して位置を特定します。
li {
color: black;
}
li:first-of-type {
color: red;
}
li:last-of-type {
color: blue;
}
li:nth-of-type(2) {
color: green;
}
<ul>
<li>li:first-of-typeなので赤文字です。</li>
<li>li:nth-of-type(2)なので緑文字です。</li>
<li>黒文字</li>
<li>黒文字</li>
<li>li:last-of-typeなので青文字です。</li>
</ul>
<ul>
<li>li:first-of-typeなので赤文字です。</li>
<li>li:nth-of-type(2)なので緑文字です。</li>
<li>黒文字</li>
<li>黒文字</li>
<li>li:last-of-typeなので青文字です。</li>
</ul>
この例とchildの例を比較すると、childとof-typeは同じ要素を指定していることが分かります。これはグルーピングされている要素がliのみであるためです。
以下の例では、childとof-typeの違いが確認できます。
.child p:nth-child(even) {
color: red;
}
.child p:first-child {
color: blue;
}
.of-type p:nth-of-type(even) {
color: red;
}
.of-type p:first-of-type {
color: blue;
}
<section class="child">
<h2>p:first-childではないので黒文字</h2>
<p>p:nth-child(even)と扱われるため赤文字</p>
<p>黒文字</p>
<p>p:nth-child(even)と扱われるため赤文字</p>
<p>黒文字</p>
</section>
<section class="of-type">
<h2>黒文字</h2>
<p>p:first-of-typeなので青文字</p>
<p>p:nth-of-type(even)なので赤文字</p>
<p>黒文字</p>
<p>p:nth-of-type(even)なので赤文字</p>
</section>
この例では、.childと.of-typeのsectionに対して疑似クラスを用いて同じ位置の要素をスタイリングしています。
.childでは、:first-childは要素の種類を区別しないため,、指定できる要素はh2のみになります。p:first-childは存在しない扱いとなり適用されません。
.of-typeでは、:first-of-typeは要素の種類を区別するため、h2, p共に:first-of-typeは指定でき、p:first-of-typeでは一番上のp要素に適用されます。
また、p:nth-child(even)で偶数番目のp要素を指定していますが、childはh2も含めて数えられるので結果的に奇数番目のp要素にスタイルが適用されています。
child, of-typeの注意点
前述のchildとof-typeの比較の例は、childを使用した場合において、pの兄弟要素が増減することでスタイルの適用される要素が変わってしまう可能性があることを意味します。
ウェブサイトは公開して終わりではなく、公開後も更新を続けることが一般的です。HTMLの要素が増減することは常に許容しなければいけません。
first-of-typeやnth-of-type()は要素の種類を区別するため、HTMLとCSSに一貫性が生まれます。つまり、p要素の兄弟要素が増減した場合でもそれがp要素でなければスタイルは保たれることになります。
ただし、of-typeを使う場合でも気をつけなければいけない点があります。
of-typeは要素の種類を区別しますが、クラスセレクタやidセレクタなどは区別されません。したがって、クラスセレクタを使用する場合、クラス名が適切に指定されていないと予期しない結果を生む可能性があります。
例として、「一番上にp要素を追加したがclass指定を忘れてしまった」ということを想定して考えてみます。
.of-type .item:nth-of-type(odd) {
color: red;
}
.of-type .item:first-of-type {
color: blue;
}
<section class="of-type">
<h2>黒文字</h2>
<p>item:first-of-typeではないので黒文字</p>
<p class="item">.item:nth-of-type(2)になるので黒文字</p>
<p class="item">.item:nth-of-type(odd)なので赤文字</p>
<p class="item">黒文字</p>
<p class="item">.item:nth-of-type(odd)なので赤文字</p>
</section>
一番上のpにはitemクラスが指定されていないので、.item:first-of-typeのスタイルは適用されません。
この挙動は簡単に理解できるかと思いますが、追加した要素が.itemと同じpであるため、.item:nth-of-type(odd)のスタイルが適用される要素まで変わってしまいます。
childやof-typeを使いこなすことでコーディングの時間を短縮することができますが、コーディング速度と保守性は基本的にトレードオフの関係にあります。
childやof-typeは使いどころを見極めることが重要なので、一定の条件や使用ルールなどを決めておくと良いでしょう。
疑似要素について
疑似要素は、指定した要素の特定の部分をスタイリングする際に使用できます。
CSSでスタイリングを行う際、装飾目的でHTMLに空のdivやspan要素を記述することがありますが、この手法を用いるとHTMLの構造を複雑に見せてしまう可能性があります。
疑似要素を使用することで、HTMLに変更を与えずに装飾用の要素を追加することができます。
ここでは、一般的に使用される疑似要素であるbefore, afterについて解説します。
装飾用の要素を追加する方法
before, afterを使用することで、指定した要素の子要素を疑似的に配置することができます。
before, afterの使い方は、親要素となる要素のセレクタの後ろに「::(コロン)」で区切って疑似要素名を記述します。以下が例です。
p::before {
content: "::before";
}
p::after {
content: "::after";
}
<p>テキストです。</p>
before, afterはデフォルトではインライン要素として扱われます。インライン要素はコンテンツに応じた幅を持ち、横に並ぶという特徴があるので、この例では以下のように表示されます。

p::beforeはp要素直下の一番上に配置され、p::afterは要素直下の一番下に配置されます。
また、該当する要素すぺてに適用されるので、複数のp要素があればそれぞれに疑似要素が追加されます。
<p>
<!-- p::beforeの位置 -->
テキストです。
<!-- p::afterの位置 -->
</p>
<p>
<!-- p::beforeの位置 -->
<strong>テキストです。</strong>
<!-- p::afterの位置 -->
</p>
before, afterは基本的には終了タグを定義できない要素には使用できません。
画像などに対してbefore, afterを使用したい場合はdivタグで囲う必要があります。
<img src="image/image.jpg" alt="before, afterを使用できません。">
<div class="img-wrap">
<img src="image/image.jpg" alt=".img-wrapにはbefore, afterを使用できます。">
</div>
before, afterを使用する際、contentプロパティの指定は必須なので、表示したいテキストがなくても記述する必要があります。
.txt-box {
padding: 1em;
border: 1px solid red;
position: relative;
width: fit-content;
}
.txt-box::before {
content: "";
display: block;
border: 1px solid blue;
position: absolute;
top: 4px;
left: 4px;
width: 100%;
height: 100%;
}
この例では、.txt-box::beforeで青い枠線を追加しています。
また、positionプロパティを使用することで枠線の位置を調整しています。この枠線は「content: “”;」の記述がないと表示されません。

before, afterを使用することでHTMLに変更を加えずに多彩な表現ができるので、アイコンや装飾を追加する場合によく使用されます。
注意点として、HTML要素ではないのでSEO的な効果やスクリーンリーダーでの読み上げは行われません。あくまで装飾目的であることを理解しましょう。
最後に
ウェブ制作初心者の方向けに擬似クラス・疑似要素の概要と基本的な使い方について解説しました。
:linkや:visited、:hover、:activeなどの疑似クラスは記述の順番に気を付ける必要があるので初心者のうちは混乱するかも知れませんが、この順番は必ず覚えなければいけないものでもなく、忘れたら調べるくらいの感覚で問題ないです。
この記事ではよく使用されるものをご紹介しましたが、疑似クラス・疑似要素は他にもたくさんあります。使いどころは少ないかもしれませんが、興味のある方は調べてみると良いでしょう。