はじめに
CSSセレクタである疑似要素と疑似クラスは有用なものが多いですが、数多く存在するため覚えきれていないという方も少なくないはずです。
今回は、この2つのセレクタについてまとめていきます。
(Experimentalな機能については除外します。)
出来るだけアルファベット順に並べていますが、クラスの意味によって順番が入れ替わっていますのでご了承ください。
疑似?擬似?
ゲシュタルト崩壊しそうな人は読み飛ばしていただいて構いません。
結論としては「疑似」にしとこって感じです
検索すると恐らく「擬似要素・擬似クラス」としているサイトが多いかもしれませんが、実はMDN Docsの中でも表記が揺れています。
意味合いもほとんど同じなようで、英語ではPseudoと表しますが、これの訳を見ても「擬似/疑似」と書いてあったりします。
では一体どちらで表記するのが正しいのでしょうか?
ざっと調べてみた感じ、「疑似」が漢語としては正しいようです。
「擬似」は恐らく日本人が作った言葉なのではないか、とのこと。
ということで本記事では「疑似」と記載します。
(実生活でも疑似を使うようにしようと思いました(小並))
疑似クラス
疑似クラスは、その要素の状態に基づいてスタイルを付与することができるものです。
CSSで記述する際は、:hover
のように、コロンを1つつけます。
selector:pseudo-class {
property: value;
}
ユーザ操作
:active
アクティブ化された要素(a
やbutton
)を指定します。
一般的にクリックボタンを押下したときにアクティブ状態となります。
リンク関連の疑似クラスである:link
、:hover
、:visited
によって上書きされるため、:link
→:visited
→:hover
→:active
の順(LVHA順)で記述するのが良いでしょう。
:focus
フォーカスが出来る要素をクリックまたはTabキーで選択したときに一致します。
フォーカスを持つ要素を含む要素を選択したい場合は、:focus-within
を使います
:focus-visible
要素が:focus
の条件に一致しているとき、UAがフォーカスしていることを明示するべきと判断された場合に適用されます。
マウスでクリックしたときはいらないけど、キーボードのTabキーで選択したときはフォーカス表示してほしいときなどに使います。
:focus-within
その要素または子孫要素にフォーカスを持つ場合に一致します。
:hover
カーソルを要素の上にかざしたときに一致します。
タッチデバイスでの使用はしばしば問題になるため考慮が必要です。
ツリー構造
:first-child
兄弟要素の中で一番最初の要素と一致します。
:last-child
兄弟要素の中で一番最後の要素と一致します。
:only-child
兄弟要素がない要素と一致します。
:nth-child()
兄弟要素の中で指定した位置と一致します。
:nth-last-child()
兄弟要素の中で指定した位置と一致します。
後ろから前にカウントしていきます。
:nth-of-type()
兄弟要素の指定した要素の中で指定した位置と一致します。
:nth-of-type()
と:nth-child()
の違い
:nth-of-type()
と:nth-child()
には、指定の要素以外の要素をカウントするかどうかの違いがあります。
前者がカウントせず、後者はカウントします。
以下の例を見てみましょう。
<section>
<h2>title</h2>
<p>text content<p>
<span>category<span>
<span>author<span>
<span>date<span>
</section>
このようなHTMLがあった場合、それぞれの指定は以下のように選択されます。
span:nth-child(3) {
color: red;
}
span:nth-of-type(3) {
color: red;
}
つまり、こういうことになります。
span:nth-child(3)
は単純に兄弟要素を上から数えて3番目、
span:nth-of-type(3)
は兄弟要素中のspanの中で上から数えて3番目、となります。
<section>
<h2>title</h2>
<p>text content<p>
<span>category<span> <!-- span:nth-child(3) -->
<span>author<span>
<span>date<span> <!-- span:nth-of-type(3) -->
</section>
:nth-last-of-type()
兄弟要素の指定した要素の中で指定した位置と一致します。
後ろから前にカウントしていきます。
:first-of-type
兄弟要素の指定した要素の最初の要素と一致します。
:last-of-type
兄弟要素の指定した要素の最後の要素と一致します。
:only-of-type
同じタグの兄弟要素がない要素と一致します。
:defined
定義されているすべての要素と一致します。
:empty
要素ノードや文字列などの子を持たない要素と一致します。
:host
Shadow DOM1のルートホスト要素と一致します。
(Web Componentsについて理解していないと十分に理解できないかもしれません。)
<custom-elem class="foo">
<div class="foo"></div>
</custom-elem>
Shadow DOM内からルートホストを選択したいときには以下のようにします。
この場合、ルートであるcustom-elem
を選択することになります。
:host {
/* styles */
}
:host()
Shadow DOMのルートホストのうち、セレクタの引数と一致するものを選択します。
<custom-elem class="foo">
<div class="foo"></div>
</custom-elem>
:host(.foo) {
/* styles */
}
:is()
:matches()
から:is()
に変わりました
引数にセレクタリストを取り、リスト中のいずれかに当てはまる要素と一致します。
header a:hover,
main a:hover,
footer a:hover {
opacity: 0.8;
}
/* :is()で書き換えるとこんな感じ */
:is(header, main, footer) a:hover {
opacity: 0.8;
}
:where()
引数にセレクタリストを取り、リスト中のいずれかに当てはまる要素と一致します。
header a:hover,
main a:hover,
footer a:hover {
opacity: 0.8;
}
/* :is()で書き換えるとこんな感じ */
:where(header, main, footer) a:hover {
opacity: 0.8;
}
:is()
と:where()
の違い
:is()
は引数内で最も詳細度の高いセレクタの詳細度になるのに対し、:where()
は詳細度が常に0になります。
:not()
引数に指定されたセレクタに一致しない要素を選択します。
使用する際いくつか注意点があります。
- 入れ子にはできない
- ルールの詳細度を上げることができる
-
#foo:not(#bar)
は#foo
の詳細度より高くなる
-
-
:not(.foo)
は「.foo
ではない要素」のため、<html>
や<body>
を含む - 祖先要素を除外できない
- 複数セレクタを指定する書き方はブラウザが未対応の場合がある
-
:not(.foo):not(.bar)
と書く
-
:root
ツリーのルート要素を選択します。
HTMLでは<html>
要素を表しますが、html
セレクタより詳細度が高くなります。
フォーム
:autofill
<input>
要素がブラウザによって自動補完されたときに一致します。
そのフィールドをユーザが編集すると一致しなくなります。
多くのブラウザで:-webkit-autofill
でbackground-color
、background-image
、color
に対して!important
でスタイルを定義しているため、CSSでは独自でスタイルが上書きできません。
:checked
ラジオボタン、チェックボックス、オプションボタン要素が選択された状態と一致します。
:default
以下に一致します。
- フォームのデフォルトボタンである送信ボタン
<button>
<input type="checkbox">
<input type="radio">
-
selected
属性を持つ<option>
:enabled
アクティブ化したりフォーカスができる要素と一致します。
例えば、disabled
属性が与えられたinput
要素には一致しません。
:disabled
:enabled
の逆です。
:indeterminate
未確定状態にあるフォーム要素と一致します。
-
radio
要素で、同じname
の値を持つ全てのラジオボタンが未選択状態のとき -
checkbox
要素で、JavaScriptでindeterminate
がtrue
に設定されているとき -
<progress>
要素で、途中のとき
:in-range
<input>
要素で入力値がmin
とmax
属性による範囲内にあるものに一致します。
:out-of-range
<input>
要素で入力値がmin
とmax
属性による範囲外にあるものに一致します。
:optional
required
属性が設定されていない<input>
、<select>
、<textarea>
要素と一致します。
:placeholder-shown
プレースホルダが表示されている<input>
、<textarea>
要素と一致します。
:read-only
読み取り専用readonly
が指定されている要素と一致します。
:read-write
ユーザが編集可能な要素と一致します。
:required
<input>
、<select>
、<textarea>
要素でrequired
属性が与えられているものと一致します。
:valid
バリデーションが成功したフォーム要素と一致します。
:invalid
バリデーションが失敗したフォーム要素と一致します。
リンク関連
:any-link
href
属性を持つ全ての<a>
、<area>
と一致します。
:link
href
属性を持つ<a>
、<area>
のうち、未訪問の要素と一致します。
:visited
href
属性を持つ<a>
、<area>
のうち、訪問済みの要素と一致します。
プライバシー上の理由から、適用できるスタイルに制約があります。
- 利用できるCSSプロパティは以下の通り
color
background-color
-
border-color
(ショートハンドではないものも含む) column-rule-color
text-decoration-color
text-emphasis-color
- 利用できるSVG属性は
fill
とstroke
- 利用できるスタイルでもアルファチャンネルは無視される
-
<link>
要素は:visited
に一致することはない -
window.getComputedStyle
2メソッドは:visited
状態ではない色の値を返す
:target
URLの#で記述するフラグメントに一致するidを持つ要素と一致します。
テキスト関連
:lang()
指定された言語に一致する要素を選択します。
つまり、言語別にスタイルを適用することが出来ます。
画面の状態
:fullscreen
全画面モードの要素に一致します。複数あればすべて選択します。
:picture-in-picture
ピクチャインピクチャモードの要素に一致します。
印刷
すべて@page
アットルールで使用されます。
:first
印刷文書の最初のページと一致します。
文書のマージン、改ページするとき前ページに印刷する最低行数を設定するorphans
、改ページするとき次ページに印刷する最低行数を設定するwindows
、ページ区切りを変更することが出来ます。
また、マージンはpx
やin
などの絶対的な長さの単位のみ使用できます。
:left
印刷文書の左側のページと一致します。
ページのmargin
、padding
、border
、background
の各プロパティを変更することができます。
:right
印刷文書の右側のページと一致します。
疑似要素
疑似要素は、その要素の特定の部分に対してスタイルを付与することができるものです。
CSSで記述する際は、::before
のように、コロンを2つつけます。
selector::pseudo-element {
property: value;
}
::after
選択した要素の子要素の最後に疑似要素を生成します。
<img>
、<br>
などの置換要素3には適用されません。
content
プロパティを用いて、要素の装飾によく使われます。
また、content
は空にして、background
に画像を設定したりして装飾することも多いです。
疑似クラスと疑似要素を見分けやすくするために、CSS3でコロン2つの表記法::after
が導入されましたが、CSS2の:after
も使用することが出来ます。
::before
選択した要素の子要素の最初に疑似要素を生成します。
その他::after
と同様です。
::backdrop
Experimentalではありますが、この要素自体はほぼ全てのブラウザで使用可能になったので記載します。
Experimentalが外されました。
何らかの要素が全画面モードで表示されたときにそのすぐ下のレイヤーに表示されるViewportサイズのボックス要素です。
これはFullscreen APIを使用して全画面モードで配置される要素やおよび<dialog>
(MDN Web Docs参照)要素を表示するときに用いられます。
全画面モードで複数の要素が配置されたときは、::backdrop
は最上位要素のすぐ下に描画されます。
::backdrop
はどの要素にも継承せず、どの要素からも継承せず、プロパティの制限もありません。
::cue
選択された要素内のWebVTTキューを指定します。VTTトラック付きのメディアで、キャプションなどをスタイル付けすることができます。WebVTTについてはこちらを参照してください。
::first-letter
ブロックレベル要素の最初の行の一番最初の文字を指定します。ただし、最初の文字より前に他のコンテンツがない場合に限ります。
単純に要素の最初の文字を識別できるとは限らないため注意が必要です。
例えば、::before
とcontent
プロパティで、要素の先頭にテキストが挿入された場合、この挿入されたコンテンツの最初の文字に一致します。
::first-line
ブロックレベル要素の最初の行を指定します。
なお、選択できる最初の行の長さは、要素・文書の幅、文字列のフォントの大きさなど、様々な要因に左右されます。
::file-selector-button
type="file"
のinput
要素を指定します。
「ファイルを選択」のようなボタンにスタイルを適用することができます。
古いWebKit/Blink互換のブラウザは-webkit
prefixが必要です。(::-webkit-file-upload-button
)
::selection
ユーザーがテキストをマウスでクリックやドラッグすることで選択した文書の一部にスタイルを適用します。
利用可能なプロパティ
- color
- background-color
- text-decoration
- text-shadow
- SVG関連 (stroke-color, fill-color, stroke-width)
::slotted()
HTMLテンプレート内にあるスロットに配置された任意の要素を指定します。
テンプレートとスロットについて
これはshadow DOM内に配置されたCSSの中で使われた時のみ機能します。
/* スロット内に配置された任意の要素を選択 */
::slotted(*) {
font-weight: bold;
}
/* スロット内に配置された<span>要素を選択 */
::slotted(span) {
font-weight: bold;
}
まとめ
以上、疑似要素と疑似クラスについてまとめました。
知らなかった要素もちらほらあり、自分もぜひ活用していきたいと思います。
参考