CSSセレクター総ざらい 第1回 基本セレクター
第1回目では、まずセレクター一般についての説明をします。次に5種類の基本セレクターについて解説します。普段の業務で使っているセレクターを今一度、基本仕様から押さえてみましょう。
2018年当時と機能は変わりませんが、セレクター名が変わったものや、実装が進んだものもあります。把握しているものは記事中で修正、追記されていますが、最新仕様も併せてご確認ください。
セレクターとは
CSSセレクターというと、普段の業務で日常的に触れているものなので、そもそも「セレクターとは何か?」と考えたことはないかもしれません。
そこで、この記事ではまず「セレクターとは何か」について考えるところから始めてみましょう。
仕様書(*後述コラム)によると、セレクターはツリー構造における要素の特定のパターンを表すものとされています。
A selector represents a particular pattern of element(s) in a tree structure.
たとえば、セレクターがdiv span
であれば、HTMLの要素のツリー構造におけるdiv要素の子要素としてのspan要素を示すことになります。
HTMLで表すならば、次のコードのような要素のパターンが想定できます。
<div>
<span></span> <!-- このspanを指す -->
</div>
<div>
<div>
<span></span> <!-- このspanも指す -->
</div>
</div>
「HTMLで表すならば」という言葉を使ったのは、セレクターはHTML/CSSだけに使われるものではないからです。最初の定義にあるように、セレクターが持つツリー構造における要素の特定のパターンを表す機能は、JavaScriptなどでも、次のように使われます。
- element.matches()関数は、要素が特定のセレクター文字列によって選択された場合に
true
を返す。それ以外の場合はfalse
を返す。 - document.querySelectorAll()関数や、セレクターを通して、ツリー構造中の要素の中から合致するものを絞り込む。
- HamlやEmmetなどのように、セレクターから、そのセレクターにマッチするマークアップを生成する。
セレクターで特定の要素のパターンを指定し、そのパターンに合致した箇所に任意の処理を行うという使われ方です。
*仕様書 Selectors Level 4
Selectors Level 4はSelectors Level 3の上位になる新しいセレクターの仕様です。Level 4ではより便利なセレクターや仕組みが追加されています。
セレクターの仕様には「CSS」という名前が付いていません(Gridの仕様はCSS Grid Layout Moduleです)。これは前述したとおり、セレクターがCSSだけのものではないことからきています。
他の仕様でも、Media Queriesは「CSS」が付いていません。メディアクエリは、HTMLのmedia属性で利用されることもあるからです。CSSの名前は付いていませんが、CSSに限定されていないだけで、どちらもCSSでよく利用される機能です。
CSSにおけるセレクター
CSSにおけるセレクターは、CSSのルールセットを適用する要素を定義します。ここではおさらいとして「セレクター」や「ルールセット」がどの部分を指すかについて触れておきます。
CSSは、スタイルを適用する対象になるセレクターと、そのスタイルを設定する宣言ブロックからなります。宣言ブロックの中には、プロパティとプロパティ値を宣言していきます。この塊をルールセットと呼びます。
/* ルールセット */
セレクター { /* 宣言ブロック */
width: 100px; /* 宣言(プロパティ:プロパティ値) */
height: 50px; /* 宣言(プロパティ:プロパティ値) */
} /* 宣言ブロック */
セレクターで特定の要素のパターンを指定し、そのパターンに合致した箇所にスタイルが適用されます。
さらに、このセレクターには詳細度があります。このシリーズの最終回で解説する予定ですが、詳細度はCSSが適用される際の重みで、重いほうが優先されます。CSSを書いていて思うようにスタイルがあたらなかったことはないでしょうか。また、順番を変えたらスタイルがあたった、セレクターを長くしたらあたったといった経験はないでしょうか。セレクターに対する理解を深めれば、そういった「なんとなく」をなくすことができます。
まずは、基本セレクターから解説していきます。
基本セレクターと属性セレクター
基本セレクターは、大きく分けて4種類のセレクターに分けられます。
- 要素型セレクター
- クラスセレクター
- IDセレクター
- 全称セレクター
また属性セレクターと呼ばれ、属性値の条件に合わせて要素を指定できるセレクターがあります。
- 属性セレクター
ぞれぞれについて解説していきます。
要素型セレクター
要素型セレクターは、HTMLの要素名をセレクターに指定します。
<div>div要素</div>
<p>p要素</p>
<div>div要素</div>
div { font-weight: bold; }
上記のHTMLとCSSでは、すべてのdiv
要素にfont-weight: bold;
があたります。
クラスセレクター
クラスセレクターは、class属性値を.
(ドット)から始めて、セレクターに指定します。HTMLがclass="my-class"
であれば、CSSでは.my-class
とします。
<div class="my-class">my-classを持つ要素</div>
<div class="your-class">my-classを持たない要素</div>
<div class="my-class our-class">my-classを持つ要素</div>
.my-class { font-weight: bold; }
上記のHTMLとCSSでは、class属性値にmy-class
を持つ要素にfont-weight: bold;
があたります。
IDセレクター
IDセレクターは、id属性値を#
から始めて、セレクターに指定します。HTMLがid="my-id"
であれば、CSSでは#my-id
とします。
<div id="my-id">#my-id</div>
#my-id { font-weight: bold; }
上記のHTMLとCSSでは、id属性値にmy-id
を持つ要素にfont-weight: bold;
があたります。
【ワンポイント】HTML上に同じid属性値を持つ要素が複数ある場合
HTML上に同じid属性値を持つ要素が複数あるという状態は、いうまでもなくHTML文書としては妥当なものではありません。
ただ、もしid属性値が重複すると、その要素は無視されるわけではなく、CSSで指定したスタイルがid属性値が重複している要素すべてに適用されます。
JavaScriptのgetElementById()
ではid属性値が重複している要素の中で、最初のものが取得できます。
全称セレクター
全称セレクターは、*
をセレクターに指定します。
<section>
<div class="my-div"></div>
<span class="my-span"></span>
</section>
* { font-weight: bold; }
全称セレクターでは、すべての要素を対象とします。上記のHTMLの場合、section
・div
・span
要素に対してfont-weight: bold;
があたります。全称セレクターは詳細度に影響を与えません。
属性セレクター
属性セレクターは、[属性名]
や[属性名=属性値]
といったかたちで、要素の持つ属性や属性と属性値をセレクターに指定します。HTMLでtype="text"
と指定していれば、CSSでは[type="text"]
と指定します。
<input type="text" disabled>
[disabled] { /* ... */ }
[type="text"] { /* ... */ }
属性セレクターでは、ここまで解説したセレクターでは表現できない、より細かい条件で要素を指定することができます。
[attr]
<div attr></div>
[attr] { /* ... */ }
attr
属性を持つ要素が対象になります。
[attr=value]
<div attr="value"></div>
[attr="value"] { /* ... */ }
attr
属性を持ち、その属性値がvalue
を持つ要素が対象になります。
【ワンポイント】属性セレクターの属性値をクォーテーションで囲む? 囲まない?
<div attr="value"></div>
attr属性値がvalueである要素を指定するセレクターは次のとおりです。
[attr=value] { /* ... */ }
[attr="value"] { /* ... */ }
属性値に空白が入らない場合は、ダブル(シングル)クォーテーションで囲っても囲まなくても問題ありません。ですが、次の例のように、属性値に空白を含めたい場合は、クォーテーションで囲む必要があります。
<div attr="The quick brown fox"></div>
このattr
属性値にThe quick brown fox
を含む要素を指定するセレクターをクォーテーションなしで記述してしまうと無効になります。
[attr=The quick brown fox] { /* ... */ }
空白を含む属性値を指定したい場合は、クォーテーションで囲みます。
[attr="The quick brown fox"] { /* ... */ }
筆者は普段から、空白の有無にかかわらず、属性セレクターを使う場合は、属性値をダブルクォーテーションで囲っています。
[attr~=value]
<div attr="value foo bar"></div>
<div attr="foo bar value"></div>
<div attr="foo value bar"></div>
[attr~="value"] { /* ... */ }
attr
属性値が空白区切りのリストでその中の一つがvalue
に一致する要素が対象になります。
[attr|=value]
<div attr="foo bar value"></div>
<div attr="foo bar value-piyo"></div>
[attr|="value"] { /* ... */ }
attr
属性値が、value
と一致するか、value
で始まり直後にハイフンが続く要素が対象になります。これは言語のサブコードを対象としたい場合使われることがあります。
たとえば、lang属性を使い、中国語の場合はスタイルを変えたいという場合に利用します。中国語と言っても簡体字や繁体字などがあり、それぞれ言語コードが異なります。簡体字であればzh-CN
であり、繁体字であればzh-TW
となります。
<div lang="zh">中国語</div>
<div lang="zh-CN">中国語(簡体字)</div>
<div lang="zh-TW">中国語(繁体字)</div>
2種類の中国語に対してスタイルをまとめてあてたい場合は、次のようなコードを書くこともできます。
[lang="zh"],
[lang="zh-CN"],
[lang="zh-TW"] { /* ... */ }
しかし、中国語の言語コードはzh-
から始まり、その中の細かい区分をサブコード(CN
やTW
)で区別しているので、まとめて中国語に対しての指定をする場合は、次のように書きます。
[lang|="zh"] { /* ... */ }
このセレクターが意味するのは「lang属性値にzh
に一致するか、zh
で始まり直後にハイフンが続く要素」となります。
【ワンポイント】[attr|=value]
のさまざまな使い方
次のようにBEM風のクラスに対して、スタイルをあてることができます。
<div class="block">0</div>
<div class="block--extend1">1</div>
<div class="block--extend2">2</div>
[class|="block"] { padding: 10px; background-color: tomato; }
.block--extend1 { background-color: limegreen; }
.block--extend2 { background-color: gold; }
あくまで、こういった利用ができるといった例ですので、推奨するわけではありません。
言語コード以外にも、ある属性値が、特定の文字列から始まったり、特定の文字列から始まりハイフンが続くようなものであったときに、このセレクターを活用できるかもしれません。
[attr^=value]
<div attr="value"></div>
<div attr="value foo bar"></div>
<div attr="valueFooBar"></div>
[attr^="value"] { /* ... */ }
attr
属性値がvalue
から始まる要素を指定します。
[attr$=value]
<div attr="value"></div>
<div attr="foo bar value"></div>
<div attr="my-value"></div>
[attr$="value"] { /* ... */ }
attr
属性値がvalue
で終わる要素を指定します。
[attr*=value]
<div attr="value"></div>
<div attr="foo bar value"></div>
<div attr="my-value"></div>
[attr*="value"] { /* ... */ }
attr
属性値にvalue
を1つ以上含む要素を指定します。
属性値の大文字と小文字を区別したくない場合
属性セレクターの閉じ括弧の前にi
またはI
を追加すると、属性値の大文字と小文字を区別しないようになります。
たとえば、次のようなHTMLを想定して、href属性値の.jpg
である要素にマッチするセレクターを書きます。
<a href="foo.jpg"></a>
href
属性値に.jpg
を持つ要素を示すセレクターは、次のとおりです。
[href*=".jpg"] { /* ... */ } /* この場合 href="http://hoge.jpg.com" にもマッチしてしまいますが一応... */
[href$=".jpg"] { /* ... */ }
これのHTMLの属性値がもし、jpg
ではなくJPG
になった場合、上記のCSSは適用されません。そこで、大文字と小文字を区別しないようにするi
を使用します。
<a href="foo.jpg"></a>
<a href="foo.JPG"></a>
[href*=".jpg" i] { /* ... */ }
[href$=".jpg" i] { /* ... */ }
このi
は、Selectors Level 4で追加された仕様です。最新のChromeやFirefox、Safariでは使用することができますが、IE 11とEdge 17では使用することができないので注意が必要です。
セレクターに使える文字、使えない文字
4.1.3 文字と活字ケース - Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification 日本語訳には、セレクターに使用できる文字の規則が書かれています。
使える文字
仕様書の重要な部分をまとめると、次のようになります。
- 文字
[a-zA-Z0-9]
およびISO 10646
のU+0080
以上の文字、さらにハイフン(-
)およびアンダースコア(_
)のみを含むことができる。 - 数字(
[0-9]
)、2つのハイフン(--
)、ハイフンの直後の数字(-[0-9]
)で開始できない。 - バックスラッシュ(
\
)で文字をエスケープできる。 - 日本語や絵文字といったものは、
\XXXX
形式のUnicodeエスケープをすることで利用できる。
まず、セレクターに使える文字に関しては、半角英数、記号は半角ハイフン(-
)と半角アンダースコア(_
)が利用できます。さらに、あまり知られていないかもしれませんが、日本語であったり絵文字といったマルチバイト文字を利用できます。
<div class="日本語">日本語です</div>
<div class="🍣">寿司です</div>
/* マルチバイト文字:日本語 */
.日本語 { /* 問題のないセレクター */ }
/* マルチバイト文字:絵文字 */
.🍣 { /* 問題のないセレクター */ }
日本語や絵文字を使ったセレクターを記述することはないかもしれませんが、セレクターとしては仕様に沿っているので有効です。
使えない文字
次に、セレクターに使えない、不正になるセレクターです。
.123 { /* 不正なセレクター */ }
.-100 { /* 不正なセレクター */ }
.--invalid { /* 不正なセレクター? */ }
数字で始まる、ハイフンの後に数字で始まる、2つのハイフンから始まるものは、セレクターとして不正になります。ただし、2つのハイフンから始まるセレクターに関してはSelectors Level 4では、問題のない有効なセレクターとなっています。2つのハイフンから始まるセレクターは、筆者が調べたところ、IE11では無効なセレクターになっていました。ChromeやFirefox、Edgeなどの最新バージョンでは使うことができました。
もしIE11で、2つのハイフンから始まるセレクターを使用したい場合は、ハイフンとハイフンの間にバックスラッシュ(\
)によるエスケープを使用します。
.--invalid { /* IE11では無効なセレクター */ }
.-\-invalid { /* IE11でも有効なセレクター */ }
-
や_
以外の半角記号は、セレクターには使用できませんが、エスケープをすれば、セレクターとして使用できます。
.(selector) { /* 不正なセレクター */ }
.\(selector\) { /* 有効なセレクター */ }
またバックスラッシュ以外のエスケープ方法では、\XXXX
形式のUnicodeエスケープをすることができます。
/* ハイフンから始まり、数字が続く場合 */
.-100 { /* 不正なセレクター */ }
.\002D \0031 \0030 \0030 { /* `\XXXX`形式のUnicodeエスケープにより有効なセレクター */ }
/* マルチバイトと半角記号を含む場合 */
.\(^o^)/ { /* 不正なセレクター */ }
.\\(\^\o\^\)/ { /* バックスラッシュによるエスケープにより有効なセレクター */ }
.\FF3C \0028 \005E \006F \005E \0029 \FF0F { /* `\XXXX`形式のUnicodeエスケープにより有効なセレクター */ }
セレクターで使用できない文字を使用する方法としては、属性セレクターを使うという手もあります。
[class*="\(^o^)/"] { /* 有効なセレクター */ }
属性セレクターを使う方法はとても簡単です。ですが、書き方によっては意図しない要素にマッチすることもあるため、属性セレクターを使う場合は注意が必要です。
まとめ
今回は4種類の基本セレクターと属性セレクターについて解説しました。特に属性セレクターに関しては、属性と属性値を条件に指定して柔軟な要素選択ができました。
次回は結合子について解説します。