necotech blog

CSSのIDセレクタ使うかどうか問題

CSSのIDセレクタは使わないというルールを設けてるコーディング規約ってありますよね。そのメリットを解説するようなブログ記事もたまに話題になっています。使わない理由としては、再利用性の低下セレクタの優先順位がclassと違うなどが挙げられると思います。ただ、これらはIDを使うルールを明確にしてやればデメリットにはなりません。

僕の場合は、IDセレクタを各ページの名前空間としてのみ使うというルールを設けています。たとえば、トップページであれば#top、ブログの記事一覧ページであれば#archiveといった感じで、1つのページ(もしくはテンプレート)につき1つのIDを割り振り、ページ固有のCSSはそのIDセレクタから指定する、といった具合です。

※CSS3の@namespaceは今回関係ありません。

具体的な構成

文章だけでは分かりづらいので、たとえば、下記のような簡単なECサイトの構成を考えてみます。

  • トップページ
    • 商品カテゴリ1
      • 商品1
      • 商品2
    • 商品カテゴリ2
      • 商品3
    • 会社案内
    • 個人情報保護方針

この時、名前空間を下記のように割り当てることが考えられます。デザインや構成によっては、#companyと#privacyをまとめて#pageなどとするケースも有り得ます。

  • #top
  • #item-category (商品カテゴリのテンプレート)
  • #item-detail (商品詳細ページのテンプレート)
  • #company
  • #privacy

こうすることで、下記のようにCSSをまとめることができます。

/* 共通パーツ */
.page-header {}
.page-footer {}
.contents {}
.common-section {}
.common-title {}

/* トップページ */
#top {}
#top section {}
#top section h2 {}

/* カテゴリ */
#item-category {}
#item-category section {}

/* ... */

簡単で明確なルールなので、誰でも理解し、適用できるかと思います。単純に、このルールを適用するだけでCSSが見やすくなると感じませんか?

最悪共通化に失敗して冗長になっても、他の名前空間(=ページ)を汚さないので崩れを心配する必要がありません。もちろんclassでも同様のことができますが、これも明確なルールを決めないと、class名自体が重複することが起こり得ます。(たとえばページ名としてのcategoryと、categoryセクションなど。これはbody.categoryとか.category-sectionのような運用ルールを作れば解決する。)

また、セクションには積極的にIDを振ったり、ヘッダやフッタもIDセレクタで指定するなど、もう少しゆるいルールでも適用可能です。webサイトの設計によっては上記よりゆるいor複雑なルールが必要なこともあるかと思います。

HTML上のどこにIDを記述する?

名前空間として使うため、そのページ固有のコンテンツを囲うかたちで書く訳ですが、<body id="top">とするか、<div id="top" class="contents">などとするか悩みどころです。理想的には、メインコンテンツのみに限定し、共通パーツは外に出してしまって影響範囲を抑えたいところです。ただ、ページによって共通パーツ内で顕著に変化があるようなサイトでは、bodyに直接付けたいケースもあるので、こればっかりは構成とデザインによるとしか言えません。サイドバーの色が各ページのイメージによって変わるとか画像が変わるとかはよくありますよね。

「IDを使うデメリット」は解消されるか

上に挙げたように、IDセレクタを使うことで再利用性の低下が懸念されますが、そもそも再利用できないもの(ページ固有のCSS)をまとめて書くために名前空間を用意するのが目的ですので、これは問題にはなりません。ページ内で同じIDは使えないという規則がありますが、このルールならその辺の単純なミスも起きません。セレクタの優先順位についても、むしろIDを使うことで優先され、ページ固有のCSSを書きやすくなるメリットがあることが分かると思います。たとえば下記のように、レイアウトが同じでページごとに背景画像が変わるケースを想像してみてください。

<div id="item-category" class="contents">
  <h2 class="common-title">カテゴリ1</h2>
  ...
</div>
category.php
<div id="item-detail" class="contents">
  <h2 class="common-title">商品1</h2>
  ...
</div>
item.php
.common-title {
  color: #333333;
  font-size: 20px;
  line-height: 50px;
  background: #FFFFFF url(img/common/title-bg.png) no-repeat right center;
}

#item-category .common-title {
  background-image: url(img/category/title-bg.png);
}

#item-detail .common-title {
  color: #000000;
  background-image: url(img/detail/title-bg.png);
}
style.css

IDを使う他のケース

CSS上ではIDセレクタは上記しか使いませんが、HTML上では下記の場合もIDを使用することがあります。

  1. ページ内リンク (主にsectionに使用)
  2. JavaScriptで特殊な動作をさせる箇所

二つ目については必ずやっているわけではありません。getElementByIdが他のDOMにアクセスする関数と比べて高速なこと、固有のアニメーションや動作が必要な箇所(たとえばカルーセルやcanvasアプリケーション)がブロック単位で識別できるようになることが、メリットとして挙げられます。が、classやdata-*属性を使うケースもあるのでケースバイケースです。


言ってることは普通のことでは?

ここまでで言ってる・やってることは、当たり前のことだったり意識せずに似たようなことをやっていたりもするかと思います。僕が大事だと思ったのは、なにかの概念(今回は名前空間)を適用し、それを意識する、これだけでコードの整理の仕方がずいぶん変わると感じたことです。あと、BEMのような冗長に見える設計(※個人の感想です)や、都度長くてユニークなID/クラス名をたくさんつけるような古臭い設計(※個人の感想です)が個人的に好きではないので、このルールになったのだと思います。

長々と書いてきましたが、「明確なルールがあればIDセレクタは使ってもよし。」と結論付けて、上記のルールで問題なく運用できるケースが大多数と感じています。

Facebook にシェア
LinkedIn にシェア
Pocket