In 'n' Out

知識を取り込み、そして発信する

セレクタとクラス設計の考え方

なぜCSSにはセレクタがあるのか

CSSを書いていると、見た目を揃えたい、少しだけ違いを出したい、という場面が必ず出てきます。そのとき、多くの場合はclassを使って解決できます。
共通のスタイルをclassにまとめ、必要な違いだけを追加のclassで表現する、という考え方はCSS設計の基本です。

完成イメージ
完成イメージ

完成イメージ図のように作るために、まずHTMLを書きます。

コード例

<p>1つ目のリスト</p>
<ul class="list">
    <li>リスト項目 1-1</li>
    <li>リスト項目 1-2</li>
    <li>リスト項目 1-3</li>
</ul>
<p>2つ目のリスト</p>
<ul class="list">
    <li>リスト項目 2-1</li>
    <li>リスト項目 2-2</li>
    <li>リスト項目 2-3</li>
</ul>

ここからCSSを指定して完成イメージ図と同じ形にしますが、条件があります。
2つのリストに共通しているのはliに枠線のみ、1つ目のリストはそれぞれの項目にすべて緑の背景色を敷き、2つ目のリストには1番目と3番目の項目に青の背景色、2番目の項目に赤い背景色を引くことが条件です。
それでは見た目を変えたい要素にclassを付けてみます。

<p>1つ目のリスト</p>
<ul class="list">
    <li class="bg-green">リスト項目 1-1</li>
    <li class="bg-green">リスト項目 1-2</li>
    <li class="bg-green">リスト項目 1-3</li>
</ul>
<p>2つ目のリスト</p>
<ul class="list">
    <li class="bg-blue">リスト項目 2-1</li>
    <li class="bg-red">リスト項目 2-2</li>
    <li class="bg-blue">リスト項目 2-3</li>
</ul>
.list{
    border: 1px solid #000000;
}
        
.bg-green{
    width: 250px;
    margin-bottom: 8px;
    background: #ceffbe;
    text-decoration: underline;
}

.bg-blue{
    width: 250px;
    margin-bottom: 8px;
    background: #89eaff;
    text-decoration: underline;
}

.bg-red{
    width: 250px;
    margin-bottom: 8px;
    background: #ffd2ed;
    text-decoration: underline;
}

出力例

1つ目のリスト

  • リスト項目 1-1
  • リスト項目 1-2
  • リスト項目 1-3

2つ目のリスト

  • リスト項目 2-1
  • リスト項目 2-2
  • リスト項目 2-3

この書き方でも、見た目は正しく再現できており、間違いというわけではありません。 しかし、すべてをclassで解決しようとすると、どこかで違和感が生まれます。
その正体は、CSSで同じ指定を何度も書いていることと、項目が増えるたびにclassを追加し続けなければならない点にあります。
classが増え続けると、どのclassが何のために付いているのか分かりにくくなり、修正や再利用が難しくなります。
そのため、classは意味のある単位で必要最小限にし、HTMLは見ただけで構造が読み取れる状態を保つことが重要です。
共通している箇所は無駄に書かず、構造を考えてすっきりさせたいと考えてHTML・CSSをリライトします。

コード例

<p>1つ目のリスト</p>
<ul class="list">
    <li>リスト項目 1-1</li>
    <li>リスト項目 1-2</li>
    <li>リスト項目 1-3</li>
</ul>
<p>2つ目のリスト</p>
<ul class="list">
    <li class="bg-blue">リスト項目 2-1</li>
    <li class="bg-red">リスト項目 2-2</li>
    <li class="bg-blue">リスト項目 2-3</li>
</ul>
.list{
    border: 1px solid #000000;
}
        
li{
    width: 250px;
    margin-bottom: 8px;
    background: #ceffbe;
    text-decoration: underline;
}

.bg-blue{
    background: #89eaff;
}

.bg-red{
    background: #ffd2ed;
}

出力例

1つ目のリスト

  • リスト項目 1-1
  • リスト項目 1-2
  • リスト項目 1-3

2つ目のリスト

  • リスト項目 2-1
  • リスト項目 2-2
  • リスト項目 2-3

同じ構造を持つliに共通の指定をまとめて、色を変えたいliにそれぞれclassを持たせることでだいぶすっきりしました。
それでも条件付けのためだけにクラスを付けたため、今後このクラス名は「この構造・この並び」を前提とした、リスト専用のクラスになってしまいました。

ここで重要なのは、classが不要だという話ではありません。
共通の見た目や意味を持つ要素にはclassが適しています。
一方で、「最初だけ」「隣り合うときだけ」といった構造や順序に依存する条件は、classで無理に表現しなくても、セレクタを使えば自然に指定できます。

CSSには親子・子孫・兄弟・nth-childといったセレクタが用意されています。
これはHTMLの構造を使って条件指定を行うためです。
次ページではその詳細を見ていきます。