タイトル: CSS属性セレクタで要素を絞り込む
SEOタイトル: CSS 属性セレクタ完全ガイド([attr=val] / 前方一致 / 後方一致 / 中間一致 / 大文字無視)
| この記事の要点 |
|
7 種類の属性セレクタ
基本例
/* href 属性を持つ a タグ全部(href 無しの a を除外) */
a[href] { color: blue; }
/* required 属性を持つフォーム要素 */
input[required] { border-color: red; }
input[required] + label::after { content: " *"; color: red; }
/* type が submit のボタン */
input[type="submit"] { background: blue; color: white; }
button[type="submit"] { /* 同様 */ }
/* disabled 状態(属性が値無しで存在) */
input[disabled] { opacity: 0.5; }
前方一致 ^=
/* 外部リンクに矢印 */
a[href^="http"] { /* http, https, http://example.com */ }
/* https のみ */
a[href^="https://"]::after { content: " 🔒"; }
/* 電話リンク */
a[href^="tel:"] { color: green; }
/* メール */
a[href^="mailto:"] { color: orange; }
/* 自サイト内リンク(先頭 / または ./ で始まる) */
a[href^="/"], a[href^="./"], a[href^="#"] { /* 内部リンクスタイル */ }
後方一致 $=
/* PDF へのリンク */
a[href$=".pdf"]::after { content: " 📄 PDF"; }
/* 画像ファイル */
a[href$=".jpg"],
a[href$=".png"],
a[href$=".webp"] { /* 画像リンク */ }
/* ZIP / アーカイブ */
a[href$=".zip"]::after { content: " ⬇️ ZIP"; }
中間一致 *=
/* YouTube のリンク */
a[href*="youtube.com"]::before { content: "▶ "; color: red; }
a[href*="youtu.be"]::before { content: "▶ "; color: red; }
/* 検索結果のハイライト(jQuery 風) */
a[href*="?q="] { background: yellow; }
/* GitHub のリンク */
a[href*="github.com"]::after { content: " 🐙"; }
単語一致 ~=
スペース区切りのリストの中に「その単語が完全に含まれる」とき。これは class 属性に最適:
/* class="btn primary large" のような並びの "btn" を狙う */
[class~="btn"] { padding: 8px 16px; }
/* これは .btn と本質的に同じ */
/* ⚠️ "*=" と異なる */
[class*="btn"] /* "button" や "btn-primary" 全部マッチ */
[class~="btn"] /* スペース区切りで "btn" ピッタリのときだけ */
ハイフン一致 |=
ハイフン区切りで「その値か、その値から始まる」とき。lang 属性で典型的に使う:
/* 日本語: lang="ja" または lang="ja-JP" 等 */
[lang|="ja"] { font-family: 'Noto Sans JP', sans-serif; }
/* 英語: lang="en", en-US, en-GB ... */
[lang|="en"] { font-family: Georgia, serif; }
/* 中国語簡体・繁体は別 */
[lang|="zh"] { font-family: 'Noto Sans SC', sans-serif; }
case insensitive i / sensitive s
/* デフォルトは sensitive(HTML 属性は大文字小文字無視のものが多いが) */
/* 大文字小文字を無視 */
a[href$=".PDF" i],
a[href$=".pdf" i] { /* どちらでもマッチ */ }
/* 拡張子マッチでは "i" を付けるのが安全 */
a[href$=".jpg" i] { /* .JPG .jpg .Jpg 全部 */ }
/* XML / SVG の属性は大文字小文字を区別するので "s" を明示することも */
[viewBox] { } /* 標準は s 扱い */
[viewBox="0 0 24 24" s] { } /* s 明示 */
data-* 属性と組み合わせ
モダンな書き方では class を増やさず、状態を data 属性で表現します:
アクティブ
非アクティブ
保留.card[data-status="active"] { border-color: green; }
.card[data-status="inactive"] { border-color: gray; opacity: .6; }
.card[data-status="pending"] { border-color: orange; }
/* 数値範囲を含めるのは難しいが、複数値の前方一致は使える */
.score[data-value^="9"],
.score[data-value^="10"] { color: gold; } /* 90点台以上 */
jQuery セレクタとの比較
| jQuery | CSS |
|---|---|
$('[name=email]') | [name="email"] |
$('[name!=email]') | 無し。:not([name="email"]) で代用 |
$('a[href^=https]') | a[href^="https"] |
$('a[href$=.pdf]') | a[href$=".pdf"] |
$('a[href*=youtube]') | a[href*="youtube"] |
$('div[data-foo]') | div[data-foo] |
複数属性セレクタの組合せ
/* 複数条件 AND(連結で書く) */
input[type="text"][required] { border: 2px solid red; }
/* 必須かつ未入力 */
input[required]:placeholder-shown { background: #fff3e0; }
/* 外部リンクで PDF(前方+後方両方マッチ) */
a[href^="http"][href$=".pdf"] {
background: url(/icon/pdf.svg) right center no-repeat;
padding-right: 20px;
}
/* type="checkbox" の選択時 */
input[type="checkbox"]:checked + label { font-weight: bold; }
パフォーマンス考慮
属性セレクタは class よりわずかに遅いですが、現代のブラウザでは実質体感差なし。気にせず使えます。ただし:
- 大量要素(数千〜)の
[attr*=...]による中間一致は若干コストがかかる - 同じ目的が class で達成できるなら class のほうがシンプル
- HTML 構造に影響しないUI 状態の表現には属性セレクタが優位(class 操作不要)
FAQ
Q: [class~="btn"] と .btn、どちらが良い?
A: 動作は同じ。.btn のほうが短くて速いので通常はそちら。属性セレクタは class 以外を含めて統一したい時に。
Q: 属性に値が無いとき(checked など)の判定
A: [checked] で OK。値の有無は問わず、属性が存在するだけでマッチ。
Q: !=(否定)は使える?
A: 単体ではなし。:not([attr=value]) で書きます: input:not([type="hidden"])。