CSS設計で気をつけること

# 前書き

今回は[このブログ記事の内容](https://yk0807.com/techblog/2019/12/17/css%e8%a8%ad%e8%a8%88%e3%81%a7%e6%b0%97%e3%82%92%e3%81%a4%e3%81%91%e3%82%8b%e3%81%93%e3%81%a8/)を移したものです。

Webシステムの開発はユーザーの方が期待する通りに動くことはもちろん大事ですが、アクセスするページの見栄えが悪かったり、どこに何があるかがわかりにくかったりすると、使う側にとって気持ちよく使えなかったりするので、Webシステムはどう見えるかも結構大切だったりします。

そこで、Webページのデザインを整える役割を持つCSSをどうやって作るかが問題になってきます。 今回は、[こちらの本](https://www.amazon.co.jp/Web%E5%88%B6%E4%BD%9C%E8%80%85%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AECSS%E8%A8%AD%E8%A8%88%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E3%83%A2%E3%83%80%E3%83%B3Web%E9%96%8B%E7%99%BA%E3%81%AB%E6%AC%A0%E3%81%8B%E3%81%9B%E3%81%AA%E3%81%84%E3%80%8C%E4%BF%AE%E6%AD%A3%E3%81%97%E3%82%84%E3%81%99%E3%81%84CSS%E3%80%8D%E3%81%AE%E8%A8%AD%E8%A8%88%E6%89%8B%E6%B3%95-%E8%B0%B7-%E6%8B%93%E6%A8%B9/dp/4844336355)を参考に、CSS設計の中でも一番基本的なところを簡単にまとめてみました。

# セレクタの詳細度

CSSの設計を考える上でまず押さえておくべきなのが、**「セレクタの詳細度」**です。セレクタとは、クラスとかIDとか、スタイルを適用させる要素のことです。ある要素に複数のスタイルが当てられているときには、詳細度の高い方が優先されます（同じ詳細度の場合は後に設定されたものが優先になります）。

セレクタの詳細度は、ずばり以下のようになります。

|        |         |                |
|:-----------------|------------------:|------------------:|
| 高 | (1) | !important |
| ↑ | (2) | インライン記述（HTMLのstyle属性） |
| ↑ | (3) | IDセレクタ |
| ↓ | (4) | クラスセレクタ・属性セレクタ・擬似クラス （button:first-childなど） |
| ↓ | (5) | 要素セレクタ・擬似要素（::after, ::beforeなど） |
| 低 | (6) | ユニバーサルセレクタ（*を使ったもので、他にスタイルが当たってないもの全てに適用される） |

例えば、

```css
#red-id {
  color: red;
}
.blue-class {
  color: blue;
}
```
このようになっていた場合、

<div id="red-id" class="blue-class">こんにちは。</div>
この「こんにちは。」はIDセレクタの方がクラスセレクタより優先度が高くなるので、赤く表示されます。

実際にはいくつかのセレクタの組み合わせで適用される要素が決まることが多く、結構複雑になりがちなのですが、例えばクラスセレクタが１つの場合と２つの場合で後者の方が優先されることになります。 このサイトを使ってみると、理解が深まるかもしれません。

この中で、(1)と(2)は保守性の観点から出来れば使わない方が望ましいのですが、なかなか思ったように表示させることができなくて、ついやってしまうことがあります。

そうならないようにも、セレクタをうまくリファクタリングすることが重要になってくるわけです。リファクタリングのコツはいろいろあるのですが、例えばこんな感じです。

# 要素セレクタを省略する

例えば、以下のようなスタイル設定があったとします。

```css
span.form-control {
    font-size: 14px;
}
```
これは、spanを省略して下のようにしても、多くの場合問題なかったりします。

```css
.form-control {
    font-size: 14px;
}
```

# セレクタを短くする
例えば、次のようなケースを考えます。

```html
<ul class="students">
 	<li><a href="/student1.html">学生１</a></li>
 	<li><a href="/student2.html">学生２</a></li>
 	<li><a href="/student3.html">学生３</a></li>
</ul>
```
これに対して、以下のスタイルを設定することを考えます。

```css
.students li a {
    font-weight: bold;
}
```

ここで、HTML5の仕様ではul要素の直下はli要素になるのですが、セレクタはそのようなマークアップの構造に縛られないので、以下のように省略することができます。

```css
.students a {
    font-weight: bold;
}
```

# セレクタを限定的にする
例えば、div .dataというふうに書くと、div要素の子要素だけでなく、それの子要素やさらにそれの子要素、・・・という風にdiv以下の全ての要素が影響を受けてしまいます。

div ＞ .dataと書けば、div要素の直下のdataクラスのみに影響範囲を狭めることができます。

# クラスセレクタを活用する
セレクタの詳細度一覧を見ても分かる通り、IDセレクタは結構強いセレクタなので、あるIDが含まれる要素の中の一部だけにスタイルを当てたい場合は、IDセレクタを使わずにその部分の要素にクラスを設定し、クラスセレクタでスタイルを設定した方がより柔軟な設計になります。

前の会社にいたときの社内のプログラマによる勉強会でCSSの設計がテーマになったことがあり、その時自分自身発表を聞いていて「あの時はこうすればよかったのか」と思ったりしたので、今回基本的なところをまとめてみました。

実際にはOOCSSとかSMACSSとか、色々な手法があるようなので、余裕がある時にさらに深く勉強して、今後のCSS設計に役立てていきたいです。

# 追記
とはいっても、例えばAdminLTEなどのCSSフレームワークを導入している場合、そっちの方の設定の方が強力でなかなか思うように設定できない場合もあったりします（しかも、AdminLTE自体が!importantを結構使っていたり）。

そういう場合どうするか悩むところですが、おとなしくCSSフレームワークの設定に合わせるか、CSSフレームワークで使っていないクラス名を設定するか、ケースバイケースとしか言えないでしょうね。もしかしたらこういう時にも定石みたいなのがあるのかもしれないですが、少なくとも僕は知らないです。

# 追記2
設定したい要素が限定的な場合はまとめて行うプロパティよりも必要な要素に対してのみ働くプロパティを使用したほうが良さそうです。

例えば、背景の色だけを変えたいと言った場合、背景に関する指定をまとめて行うbackgroundよりも、背景色の設定のみを行うbackground-colorを使うといった感じです。

```css
.input-form {
  background:red;
}
```
ではなく、

```css
.input-form {
  background-color:red;
}
```
みたいな感じです。