タイトル: CSS の id セレクタ(#id)と詳細度・代替パターン
SEOタイトル: CSS id セレクタ #id の使い方・詳細度・id を使うべきでない理由(class / data-* 推奨)
| この記事の要点 |
|
id セレクタの基本
<style>
#header {
background: #333;
color: white;
padding: 20px;
}
#header h1 {
margin: 0;
}
</style>
<header id="header">
<h1>サイトタイトル</h1>
</header>
id と class の違い
| 項目 | id (#name) | class (.name) |
|---|---|---|
| HTML 内の数 | ★1 つだけ(一意) | 複数可 |
| 1 要素に複数指定 | 不可 | 可(class="a b c") |
| 詳細度 | 0,1,0,0(高い) | 0,0,1,0 |
| JS アクセス | getElementById 直接 | getElementsByClassName |
| アンカーリンク | <a href="#name"> | 不可 |
| ARIA labelledby | aria-labelledby="id" | 不可 |
| 用途 | JS フック / アンカー | ★スタイル用 |
詳細度の罠
id の詳細度は 0,1,0,0。class や属性セレクタを 10 個重ねても勝てません:
/* これは id に勝てない */
.header.dark.fixed.main { background: blue; } /* 0,0,4,0 */
/* これも勝てない */
header.fixed[role="banner"] { background: blue; } /* 0,0,2,1 */
/* これが必要になる… */
#header { background: red; } /* 0,1,0,0 */
/* 上書きするには id を使うか !important */
#header.dark { background: blue; } /* 0,1,1,0 */
.header { background: blue !important; } /* !important */
/* よくある悲劇: id+!important の連鎖
元: #header { color: red; }
改修1: #header { color: blue !important; }
改修2: ......(打つ手なし) */
id セレクタを使うべきでない理由
- 再利用できない — 1 ページに 1 つしか置けない
- 詳細度が高すぎる — 後から class で上書きできない
- 大規模化で衝突 — チームメンバ間で同じ id を付けがち
- BEM / SMACSS / CSS Modules 等のメソドロジに合わない
原則として:
/* ✅ 推奨: class でスタイル */
.header { ... }
.header__title { ... }
.header--dark { ... }
/* ✅ id は JS / アンカー / aria 用途のみ */
#main-content { /* 中身は CSS で何も指定しない */ }<a href="#main-content" class="skip-link">本文へスキップ</a>
<main id="main-content" class="content">
<h2 id="section1" class="section">セクション1</h2>
...
</main>
<script>
// JS フックは id 推奨
document.getElementById('main-content').focus();
</script>
JavaScript からの id 利用
// 最速: getElementById は専用最適化
const el = document.getElementById('main');
// 同等: querySelector でも可
const el2 = document.querySelector('#main');
// 一意性が壊れていると...
// HTML 内に id="main" が 2 つある場合
// getElementById: 最初の要素を返す(順序依存)
// querySelectorAll('#main'): 全部返るので NodeList で確認可能
// 動的生成時の id 衝突回避
function uniqueId(prefix = 'el') {
return `${prefix}-${crypto.randomUUID()}`;
}
const id = uniqueId('modal');
ARIA 属性での id 必須ケース
アクセシビリティでは id 参照が必須の場面があります:
<!-- ラベル参照 -->
<label id="lbl-name">名前</label>
<input aria-labelledby="lbl-name">
<!-- 説明文 -->
<input aria-describedby="hint-pwd">
<p id="hint-pwd">8文字以上、英数字混在</p>
<!-- ダイアログ -->
<div role="dialog" aria-labelledby="dlg-title" aria-describedby="dlg-desc">
<h2 id="dlg-title">確認</h2>
<p id="dlg-desc">削除してよろしいですか?</p>
</div>
<!-- フォーム要素とラベル -->
<label for="email">メール</label>
<input id="email" type="email">
id が重複したときの挙動
<div id="dup">A</div>
<div id="dup">B</div>
<style>
#dup { color: red; } /* どちらも赤くなる(CSS は全部に適用) */
</style>
<script>
document.getElementById('dup'); // 最初の <div>A</div> を返す
document.querySelectorAll('#dup'); // 両方の NodeList を返す
// <a href="#dup"> でジャンプ → 最初の方
// フォームラベル <label for="dup"> → 最初の方
</script>
HTML 仕様違反であり、id 重複は必ず避けるべきです。
CSS Modules / styled-components 時代の解決
モダンフロントエンドでは id 衝突回避のため、ビルド時にハッシュ化された classを生成します:
// CSS Modules
import styles from './Header.module.css';
<header className={styles.header}>...</header>
// → 実際の class は "Header_header__a3f2k"
// styled-components
const Header = styled.header`
background: #333;
color: white;
`;
<Header>...</Header>
// → class 名は自動生成 "sc-bdVaJa pZksv"
// Tailwind CSS(ユーティリティ)
<header class="bg-gray-800 text-white p-5">...</header>
// CSS Layer で詳細度を管理
@layer reset, base, components, utilities;
@layer components {
.header { ... }
}
FAQ
Q: id にハイフンや数字は使える?
A: 使える。ただし数字始まりは古い CSS で問題出る場合があるので、英字始まり推奨。
Q: 詳細度を下げて id をスタイルに使いたい
A: :where(#id) { ... } で詳細度 0 に。新しい技。
Q: id を JS と CSS で別の名前にしたい
A: 要素には id (JS 用) と class (CSS 用) を両方持たせる。<div id="modal-root" class="modal">