CSS Podcast - 015: 疑似クラス
たとえば、メール登録フォームがあり、無効なメールアドレスが含まれている場合は、メール フォーム フィールドの枠線を赤色にしたいとします。その方法は、:invalid CSS 疑似クラスを使用できます。これは、ブラウザが提供する多くの疑似クラスの 1 つです。
疑似クラスを使用すると、状態の変化や外部要因に基づいてスタイルを適用できます。つまり、無効なメールアドレスなどのユーザー入力にデザインが反応するようになります。これらについては、セレクタ モジュールで説明します。このモジュールでは、これらのセレクタについて詳しく説明します。
前のモジュールで詳しく説明した疑似要素とは異なり、疑似クラスは、要素の特定の部分をスタイル設定するのではなく、要素が取りうる特定の状態にフックします。
インタラクティブな状態
次の疑似クラスは、ユーザーがページを操作したときに適用されます。
:hover
ユーザーがマウスやトラックパッドなどのポインティング デバイスを使用して要素にカーソルを合わせた場合、:hover を使用してその状態をフックし、スタイルを適用できます。これは、要素を操作できることを示すのに便利な方法です。
:active
この状態は、クリックがリリースされる前に、要素がクリックなどの操作をアクティブに受けているときにトリガーされます。マウスなどのポインティング デバイスが使用されている場合、この状態はクリックが開始され、まだリリースされていない状態です。
:focus、:focus-within、:focus-visible
要素がフォーカスを受け取ることができる場合(<button> など)、:focus 疑似クラスを使用してその状態に反応できます。
要素の子要素がフォーカスを受け取った場合に :focus-within で反応することもできます。
ボタンなどのフォーカス可能な要素は、クリックされた場合でも、フォーカスされるとフォーカス リングを表示します。このような状況では、デベロッパーは次の CSS を適用します。
button:focus {
outline: none;
}
この CSS は、要素がフォーカスを受け取ったときにブラウザのデフォルトのフォーカス リングを削除します。これは、キーボードでウェブページを移動するユーザーにとってアクセシビリティの問題となります。フォーカス スタイルがないと、Tab キーを使用しているときに、現在フォーカスがどこにあるかを把握できません。:focus-visible を使用すると、キーボードで要素にフォーカスが当たったときにフォーカス スタイルを表示し、ポインタ デバイスが要素を操作したときに outline: none ルールを使用してフォーカス スタイルを非表示にできます。
button:focus {
outline: none;
}
button:focus-visible {
outline: 1px solid black;
}
:target
:target 疑似クラスは、URL フラグメントと一致する id を持つ要素を選択します。次のような HTML があるとします。
<article id="content">
<!-- ... -->
</article>
URL に #content が含まれている場合、その要素にスタイルを適用できます。
#content:target {
background: yellow;
}
これは、スキップリンクを使用して、ウェブサイトのメイン コンテンツなど、特定のリンク先となる可能性のある領域をハイライト表示する場合に便利です。
履歴の状態
:link
:link 疑似クラスは、まだアクセスされていない href 値を持つ任意の <a> 要素に適用できます。
:visited
:visited 疑似クラスを使用すると、ユーザーがすでにアクセスしたリンクのスタイルを設定できます。これは :link とは逆の状態ですが、セキュリティ上の理由から使用できる CSS プロパティが少なくなります。スタイルを設定できるのは、color、background-color、border-color、outline-color と、SVG の fill と stroke の色のみです。
順序の重要性
:visited スタイルを定義した場合、少なくとも同等の特異性を持つリンク擬似クラスでオーバーライドできます。そのため、特定の順序(:link、:visited、:hover、:active)で疑似クラスを使用してリンクのスタイルを設定する場合は、LVHA ルールを使用することをおすすめします。
a:link {}
a:visited {}
a:hover {}
a:active {}
フォームの状態
次の疑似クラスは、フォーム要素が操作中に取りうるさまざまな状態にあるときに、フォーム要素を選択できます。
:disabled、:enabled
<button> などのフォーム要素がブラウザによって無効になっている場合、:disabled 疑似クラスを使用してその状態にフックできます。:enabled 疑似クラスは反対の状態に使用できますが、フォーム要素もデフォルトで :enabled であるため、この疑似クラスを使用することはあまりないかもしれません。
:checked、:indeterminate
:checked 疑似クラスは、チェックボックスやラジオボタンなどのサポート対象のフォーム要素がチェックされている状態の場合に使用できます。
:checked 状態はバイナリ(true または false)状態ですが、チェックボックスには、オンでもオフでもない中間状態があります。これは :indeterminate 状態と呼ばれます。
この状態の例としては、グループ内のすべてのチェックボックスをオンにする [すべて選択] コントロールがある場合などがあります。ユーザーがこれらのチェックボックスのいずれかをオフにすると、ルート チェックボックスは「すべて」がオンになっている状態を表さなくなるため、不確定状態にする必要があります。
<progress> 要素には、スタイル設定可能な不確定状態もあります。一般的なユースケースは、ストライプ模様にして、必要な残りの量が不明であることを示すことです。
:placeholder-shown
フォーム フィールドに placeholder 属性があり、値がない場合、:placeholder-shown 疑似クラスを使用して、その状態にスタイルを適用できます。フィールドにコンテンツが入力されると、placeholder の有無にかかわらず、この状態は適用されなくなります。
検証状態
:valid、:invalid、:in-range などの疑似クラスを使用して、HTML フォームの検証に応答できます。:valid と :invalid の疑似クラスは、有効なフィールドにするために pattern と一致させる必要があるメール フィールドなどのコンテキストで役立ちます。この有効な値の状態をユーザーに表示することで、次のフィールドに安全に移動できることをユーザーに理解させることができます。
:in-range 疑似クラスは、入力に min と max があり、数値入力と値がその範囲内にある場合に使用できます。
HTML フォームでは、required 属性を使用してフィールドが必須であることを指定できます。必須フィールドには :required 疑似クラスが使用できます。必須でないフィールドは、:optional 疑似クラスで選択できます。
インデックス、順序、出現回数による要素の選択
ドキュメント内の位置に基づいて項目を選択する疑似クラスのグループがあります。
:first-child、:last-child
最初または最後のアイテムを見つけるには、:first-child と :last-child を使用します。これらの疑似クラスは、兄弟要素のグループの最初または最後の要素を返します。
:only-child
:only-child 疑似クラスを使用すると、兄弟要素のない要素を選択することもできます。
:first-of-type、:last-of-type
:first-of-type と :last-of-type を選択できます。これらは一見すると :first-child や :last-child と同じように見えますが、次の HTML を考えてみましょう。
<div class="my-parent">
<p>A paragraph</p>
<div>A div</div>
<div>Another div</div>
</div>
この CSS:
.my-parent div:first-child {
color: red;
}
最初の子要素は段落であり、div ではないため、要素は赤色になりません。このコンテキストでは、:first-of-type 疑似クラスが役立ちます。
.my-parent div:first-of-type {
color: red;
}
最初の <div> は 2 番目の子要素ですが、.my-parent 要素内の最初の型であるため、このルールでは赤色になります。
:nth-child、:nth-of-type
最初の子と最後の子、タイプに限定されることもありません。:nth-child と :nth-of-type の疑似クラスを使用すると、特定のインデックスにある要素を指定できます。CSS セレクタのインデックスは 1 から始まります。
:nth-last-child() と :nth-last-of-type() の疑似クラスは、先頭ではなく末尾からカウントします。
これらの疑似クラスには、インデックスだけでなく、さまざまな値を渡すことができます。偶数番目の要素をすべて選択する場合は、:nth-child(even) を使用します。
An+B マイクロ構文を使用すると、等間隔でアイテムを見つけるより複雑なセレクタを作成することもできます。
li:nth-child(3n+3) {
background: yellow;
}
このセレクタは、3 番目の項目から 3 つおきに項目を選択します。この式では、n はインデックスで、ゼロから始まります。3(3n)はインデックスに乗算する値です。
たとえば、<li> アイテムが 7 個あるとします。最初に選択される項目は 3 です。これは、3n+3 が (3 * 0) + 3 に変換されるためです。次のイテレーションでは、n が 1 に増分されたため、(3 * 1) + 3) となり、項目 6 が選択されます。この式は :nth-child と :nth-of-type の両方で機能します。
:nth-child() と :nth-last-child() は、「of S」構文もサポートしています。この構文を使用すると、:nth-of-type() と同様に、セレクタを使用して一致をフィルタできます。li:nth-of-type(even) は :nth-child(even of li) と同等です。:nth-of-type では要素のタイプ(li や p など)に基づいてフィルタリングできますが、「of S」構文では任意のセレクタに基づいてフィルタリングできます。
表がある場合は、行を 1 行おきにストライプにすることができます。tr:nth-child(even) を使用して 1 行おきにターゲットを設定できますが、一部の行をフィルタで除外している場合は機能しません。hidden 属性を適用してフィルタリングを実装する場合は、セレクタに of :not([hidden]) を追加して、偶数行を選択する前に非表示の項目を事前にフィルタリングできます。
tr:nth-child(even of :not([hidden])){
background: lightgrey;
}
この種のセレクタは、こちらの nth-child テスターまたはこちらの数量セレクタ ツールで試すことができます。
:only-of-type
最後に、:only-of-type を使用して、兄弟のグループ内の特定のタイプの唯一の要素を見つけることができます。これは、アイテムが 1 つしかないリストを選択する場合や、段落内の唯一の太字要素を見つける場合に便利です。
空の要素を見つける
完全に空の要素を特定することが役立つ場合もあります。そのための疑似クラスもあります。
:empty
要素に子がない場合、:empty 疑似クラスが適用されます。ただし、子要素は HTML 要素やテキストノードだけではありません。空白文字も子要素になることがあります。次の HTML をデバッグしていて、:empty で動作しない理由がわからない場合は、混乱する可能性があります。
<div>
</div>
これは、開始タグと終了タグの <div> の間に空白があるため、:empty が機能しないことが原因です。
:empty 疑似クラスは、HTML をほとんど制御できず、WYSIWYG コンテンツ エディタなどの空の要素を非表示にしたい場合に便利です。ここでは、エディタが空の段落を追加しています。
<article class="post">
<p>Donec ullamcorper nulla non metus auctor fringilla.</p>
<p></p>
<p>Curabitur blandit tempus porttitor.</p>
</article>
:empty を使用すると、その投稿を見つけて非表示にできます。
.post :empty {
display: none;
}
複数の要素を検索して除外する
擬似クラスを使用すると、よりコンパクトな CSS を記述できます。
:is()
.post 要素内の h2、li、img の子要素をすべて見つけたい場合は、次のようなセレクタ リストを記述することを考えるかもしれません。
.post h2,
.post li,
.post img {
…
}
:is() 疑似クラスを使用すると、より簡潔なバージョンを記述できます。
.post :is(h2, li, img) {
/* ... */
}
:is 疑似クラスは、セレクタ リストよりもコンパクトであるだけでなく、寛容性も高くなっています。ほとんどの場合、セレクタ リストにエラーまたはサポートされていないセレクタが含まれていると、セレクタ リスト全体が機能しなくなります。:is 疑似クラスで渡されたセレクタにエラーがある場合、無効なセレクタは無視されますが、有効なセレクタは使用されます。
:not()
:not() 疑似クラスを使用してアイテムを除外することもできます。たとえば、class 属性のないすべてのリンクのスタイルを設定するために使用できます。
a:not([class]) {
color: blue;
}
:not 疑似クラスは、アクセシビリティの向上にも役立ちます。たとえば、<img> には空の値であっても alt が必要です。そのため、無効な画像に太い赤いアウトラインを追加する CSS ルールを記述できます。
img:not([alt]) {
outline: 10px red;
}
:has()
要素の内容に基づいてスタイルを設定したい場合はどうすればよいでしょうか?これを行うには、:has() 疑似クラスを使用します。たとえば、アイコンを含むボタンにスタイルを適用できます。
button:has(svg) {
/* ... */
}
前の例のように、最も基本的な構成では、:has() は親セレクタと考えることができます。一致する親セレクタを他のセレクタと組み合わせて、他の要素をターゲットにすることもできます。
form:has(input:valid) label {
font-weight: bold;
}
form:has(input:valid) label::after {
content: "✅";
}
この例では、フォーム入力に valid 疑似クラスがある場合に、ラベル要素と label::after 疑似要素にスタイルを適用しています。
:has() 疑似クラスを別の :has() の中にネストすることはできませんが、他の疑似クラスと組み合わせることはできます。
:is(h1, h2, h3):has(a) {
/* ... */
}
セレクタ リストは厳密であるため、リスト内のセレクタが無効な場合、すべてのスタイルルールが無視されます。
.my-element:has(img, ::before) {
/* any styles here will be discarded since pseudo elements can't be included in the :has() selector list */
}
理解度を確認する
疑似クラスに関する知識をテストする
疑似クラスは、クラスが要素に動的に適用されたかのように動作しますが、疑似要素は要素自体に作用します。
: がキーの区別文字として使用されているかどうかを確認します。次のうち、関数型疑似クラスはどれですか?
:is():target() が付いています。:empty() が付いています。:not()次の疑似クラスのうち、ユーザー操作によるものはどれですか?
:hover:press:squeeze:target:focus-within<form> 状態疑似クラスは次のうちどれですか?
:enabled:fresh:indeterminate:checked:in-range:loading:valid