コラム・豆知識
HTML仕様における一意なID属性の必須性
HTML仕様では、id属性の値はドキュメント内で一意でなければなりません。同じIDを複数の要素に付与すると、W3Cバリデーターでエラーが検出されます。ブラウザは寛容に表示を試みますが、予期しない動作が発生するリスクがあります。
document.getElementById()メソッドは、最初に見つかった要素のみを返します。重複IDがある場合、2番目以降の要素はJavaScriptから正常にアクセスできません。動的な操作を前提としたUIコンポーネントで、この問題が顕在化します。特定の要素だけが動作し、他が無反応という不可解なバグの原因となります。
CSSの#idセレクタも、最初にマッチした要素にのみスタイルが適用される場合があります。ブラウザの実装により挙動が異なるため、一貫性のないデザインを招きます。本来はclass属性を使用すべき箇所で、誤ってidを使用している可能性が高いです。
アンカーリンクでの#id参照も影響を受けます。<a href="#section1">で同じIDが複数存在すると、最初の要素にしかジャンプしません。ページ内ナビゲーションが正常に機能せず、ユーザーエクスペリエンスを損ないます。単純なコピー&ペーストによる重複が、実害をもたらす典型例です。
大規模開発における重複ID発生の原因と予防
コンポーネント単位での開発が主流の現在、同じコンポーネントを複数配置する際にID重複が発生しやすくなっています。React やVueといったフレームワークでは、プロップスやステート値を使って動的にIDを生成することで、この問題を回避できます。id={`item-${index}`}のようなパターンが一般的です。
複数人での並行開発では、命名規則の不統一が重複の温床となります。「header」「nav」「footer」といった汎用的な名前を各開発者が独立に使用すると、マージ時に衝突します。BEM記法やFLOCSS設計のような、体系的な命名規則の導入が予防策となります。
CMSのテンプレート構造でも注意が必要です。サイドバーウィジェットやフッターコンポーネントが複数ページで共通利用される場合、各ページで同じIDが出力される設計ミスが起こり得ます。WordPressのテーマ開発では、get_the_ID()などの動的値を組み込む配慮が求められます。
レガシーコードのリファクタリング時、既存のID構造を維持しながら新機能を追加すると、意図せず重複が生じます。全体の構造を俯瞰せずに部分的な修正を重ねた結果、整合性が失われます。定期的な全体検証と、自動チェックツールの導入が品質維持に不可欠です。
アクセシビリティとARIA属性での影響範囲
aria-labelledbyやaria-describedby属性は、ID参照により関連要素を紐付けます。重複IDが存在すると、スクリーンリーダーは誤った要素を参照し、支援技術ユーザーに不正確な情報を提供します。視覚的には問題なくても、アクセシビリティが著しく損なわれます。
label要素のfor属性も同様です。<label for="email">が複数の<input id="email">に対応しようとすると、最初の入力欄にのみラベルが関連付けられます。フォーム全体でのユーザビリティが低下し、入力ミスの原因となります。
WCAG 2.1のガイドラインでは、プログラムによる関連付けの正確性が求められています。重複IDは、この基準に違反する構造的な問題です。アクセシビリティ監査ツール(axe DevTools、WAVE等)では、重複IDが自動検出され、深刻度の高い問題として報告されます。
キーボードナビゲーションでの:focus状態も影響を受ける場合があります。getElementById()を使用したフォーカス制御で、意図しない要素にフォーカスが移動すると、キーボードのみのユーザーが操作不能に陥ります。法的要求が厳格化する現在、この問題は訴訟リスクにもつながります。
自動テストとCIパイプラインへの統合
HTML バリデーションをCIプロセスに組み込むことで、重複ID検出を自動化できます。html-validate やnu-html-checker といったツールを、GitHubActionsやGitLab CIで実行し、マージ前に問題を検知できます。プルリクエスト時のチェック項目として定義することで、品質ゲートとして機能します。
E2Eテスト(Playwright、Cypress)でも、重複IDの存在を検証できます。特定のIDを持つ要素数をカウントし、2以上であればテストを失敗させるアサーションを記述します。実際のブラウザ環境での動作確認と併せて、構造上の問題も検出できる統合的なアプローチです。
Storybookでのコンポーネントカタログ作成時、各ストーリーで重複IDが発生していないか確認できます。同じコンポーネントを複数インスタンス化する際の問題を、開発段階で発見できます。視覚的なレグレッションテストと構造検証を同時に実施する効率的な手法です。
Lighthouseの自動実行により、アクセシビリティスコアの低下を検知できます。重複IDがアクセシビリティ評価に影響するため、スコア変動のトリガーとして機能します。数値的な品質指標として管理し、継続的な改善サイクルを確立できます。
実務での修正戦略とリファクタリング手順
重複IDの修正では、どちらのIDを変更するか、慎重な判断が必要です。既存のJavaScriptやCSSで参照されている場合、影響範囲の調査が前提条件です。grepコマンドやIDEの全文検索により、該当IDの使用箇所をすべて洗い出します。
多くの場合、片方のIDはclass属性への変更が適切です。複数要素に共通のスタイルやJavaScript処理を適用する意図であれば、本来classを使用すべきでした。CSSセレクタを#idから.classに変更し、JavaScriptはquerySelectorAll()を使用するリファクタリングが標準的です。
どうしても一意なIDが必要な場合、接頭辞や連番による区別が有効です。header-primaryとheader-secondary、またはitem-1、item-2のような命名により、意味を保ちながら一意性を確保できます。自動生成されるIDでは、タイムスタンプやランダム文字列の付与も選択肢です。
段階的な修正により、リスクを分散できます。まず開発環境での変更と動作確認、次にステージング環境での全体テスト、最後に本番環境へのデプロイという手順を踏むことで、予期しない不具合を最小限に抑えられます。1ページずつ、1コンポーネントずつ修正し、その都度検証する慎重なアプローチが、大規模サイトでの安全な改善につながります。