初心者による初心者向けのSMACSSまとめ

#SMACSSとは？
**SMACSS** とは **S**calable and **M**odular **A**rchitecture for **CSS** の略で、「スマックス」と読みます。
[SMACSSの公式サイト](https://smacss.com/)では、「CSSをより体系立て、より構造化させることで制作とメンテナンスをより容易に行うテクニック」と書かれており、サイトの運用をしていく中で、CSSを中心としたWEBコーディングを効率的に行うための考え方です。

#SMACSSで設計する目的
[SMACSSの公式サイト](https://smacss.com/)では、CSSをカテゴライズすることの目的を『デザインの中で繰り返されるパターンを体系立てるため』と解説しています。

繰り返しのパターン化によるメリットとしては、次のことが挙げられています。

 - コード量が少なくなる
 - メンテナンス性を高める
 - ユーザー体験の一貫性の向上

これらはどんなサイトでもメリットとなるため、小規模から大規模まで、さまざまなサイトでSMACSSの考え方は有用であると言えるでしょう。

#CSSのカテゴライズ
CSSのカテゴライズはSMACSSの大きな特徴的手法であり、CSSのルールを5種類にカテゴライズした上で、それぞれの考え方や記述ルールを取り決めています。

| ルール | 内容 |
|:-----------------|:------------------|
| ベース | 要素そのもののデフォルトスタイルを定義します |
| レイアウト | ページをエリアごとに分割するためのスタイルを定義します |
| モジュール | 再利用可能な単位でパーツの見た目を定義します |
| 状態（ステート） | レイアウトやモジュールの特定の状態におけるスタイルを定義します |
| テーマ | サイトのルック＆フィールを定義します |

それぞれのルールについて、もう少し詳しく見ていきます。

##ベースルール
ベースルールは、サイト全体で要素そのもののデフォルトスタイルを定義します。

ベースルールでは、主に次のセレクタを使ってスタイルを適用します。要素そのものの見た目を定義するという性質のため、**IDやクラスは使いません。**

 - 要素セレクタ　ex) body、a
 - 属性セレクタ　ex) input[type=text]
 - 擬似クラスセレクタ　ex) a:hover

```css:
body {
  background: white;
} 
input[type=text] {
  letter-spacing: 0;
}
a:visited {
  color: navy;
}
```

ここで注意したいのは、要素セレクタに対してあまりにも具体的なスタイルを指定をしてしまうと、後々その要素を使った別の見た目のモジュールを追加したくなった場合に、ベースのスタイルをすべて上書きしなければならなくなるということです。
なるべく、サイト全体で共通させたい基本的なスタイルのみに留めましょう。

また、Normalize.cssなどによるCSSリセットも、SMACSSではベースルールとなります。

##レイアウトルール
レイアウトルールでは、ページのエリア分けを行います。
ここではあくまでエリア分けに徹し、フォントや色などの見た目に関することは、後に説明するモジュールルールや状態ルールの方で指定します。
これは、CSSの再利用性を高め、CSSの上書きなどを防ぎ、コード量を減らすためです。
そして、レイアウトルールのクラス名はプレフィックスで```l-```や```layout-```などをつけて、一目でわかるようにしておきます。
（コード量を短くするためにも、```l-```を使用することを推奨します。）

```css:
.l-main {
  width: 70%;
}
.l-sub {
  width: 30%;
}
.l-fixed .l-main {
  width: 600px;
}
.l-grid-2 {
  width: 48%;
  margin: 0 0.5%; 
}
.l-grid-3 {
  width: 32.3%;
  margin: 0 0.5%;
}
```
レイアウトでは.l-grid-1~nといった風に幅が違うクラスを量産しておくことで、レイアウトの調整を容易にできます。
また、同じクラス名に対する分岐は、子孫セレクタを使います。
この場合は、```.l-fixed```を親要素に付与することで、リキッドレイアウトのデザインから、固定レイアウト用のデザインに変更しています。

また、IDセレクタはCSSの詳細度を高めてしまい、場合によってはCSSを複雑にしてしまうので利用する場合には注意が必要です。
SMACSSでも、むやみな使用をあまり推奨していません。
ページ内アンカーやJavaScriptのフックとして利用する場合は別として、それ以外は**classセレクタのみで運用することに統一**していた方が、コーディングルールとしても運用しやすいでしょう。

##モジュールルール
モジュールルールでは再利用可能な単位でパーツの具体的な見た目の定義をしていきます。
例えば、以下のような単位となります。

 - ロゴ
 - ナビゲーション
 - タブ

レイアウトとモジュールを実際に組み合わせてコーディングしてみると、以下のようなイメージとなります。

```html:
<div class="l-container-12">
  <div class="l-grid-06">
    <div class="box"><p class="box-text">box1</p></div>
  </div>
  <div class="l-grid-06">
    <div class="box"><p class="box-text">box2</p></div>
  </div>
</div>
```

### モジュールの命名規則

**プレフィックス**
先ほどの例で挙げたように、子モジュールの名前は親モジュールの名前をプレフィックスでつけます。

**クラス名をつけるタイミング**
モジュール全部にクラスを付ける必要はない。
基本的に最下層となるタグ（ex：p、a、b、li、h2）は階層が変わったりする可能性も高いので、いちいちプレフィックスを変更する必要の無いよう、クラス名をつけずに子孫セレクタの形で指定しておく方がメンテナンス性が上がる。
pタグやliタグなどの子要素ができる場合には>で指定するのがベストプラクティス。

**親要素での使い分けはしない**
同じ要素だけど置く場所が違うものは、親要素によっての指定をしない。

```html:
<div class="l-main">
  <div class="search">~</div>
</div>
<div class="l-sub">
  <div class="search">~</div>
</div>
```
こうじゃなくて

```html:
<div class="l-main">
  <div class="search">~</div>
</div>
<div class="l-sub">
  <div class="search search-vertical">~</div>
</div>
```
こうします。
```.search-vertical```に指定することで、どこに移動してもスタイルを維持できます。
つまり、モジュールはモジュールルールで独立させ、レイアウトルールの親要素によってデザインが変動的にならないようにする。
**レイアウトクラスの子孫に指定して良いのは、レイアウトクラスのみ**とし、
**モジュールクラスの子孫に指定して良いのは、モジュールクラスのみ**としましょう。

##状態ルール　
特定の状態によってスタイルを上書きします。
（状態の切りかえはJavascriptやサーバ上で動くプログラムで行います）
プレフィックスは```is-```を使います。

表示を切り替えるだけなどの簡単な状態は以下のように独立的なクラス名を用います。

```css:
.is-hidden {}
.is-error {}
.is-active {}
```

見た目が変わるものは、モジュール名を付けてあげることで競合を防げます。

```css:
.is-dialog-focus {}
.is-tab-active {}
```

##テーマルール
テーマルールでは、サイト全体の見た目の雰囲気を統一させるための定義をします
色に関わる部分などがテーマの管理対象となるので、例えば以下のように色に関するスタイルは、独立させて記述します。

```css:main.css
.box {
  border: 1px solid;
}
```

```css:theme.css
.box {
  background-color: #eee;
  border-color: #ccc;
}
```

また、枠の色や背景色など、再利用性の高いものはプレフィックスに```theme-```や```t-```を付けて用意します。

```css:
.theme-border {
  border-color: #ccc;
}
.theme-background {
  background-color: #eee;
}
```

#まとめ
SMACSSの考え方に沿ったCSSの設計をしておけば、**メンテナンス性の向上とCSSの再利用性(コード記述量の低下)は飛躍的に高まる**でしょう。

しかしルールが明確でもある分、チームなどで運用する際には、その**ルールと目的を全員に事前に共有しておかなければ破綻に繋がりかねません。**注意しましょう。
（これは他のCSS設計手法においても同様のことが言えます。その点、SMACSSはチームメンバー内での事前共有が少なくても、実際に記述されてるコードを参考に、その特徴を察してもらいやすい記述法ではあるかもしれません。）

また、CSSルールのカテゴライズなど特徴的な考え方の強い面があるため、サイトの運用途中からSMACSSに乗り換えたり、逆にSMACSS以外のCSS設計に乗り換えるのには一苦労しそうです。
**実際の開発作業に入られる前に、しっかりと検討した上で導入されることをオススメします。**