CSSアーキテクチャについて軽くまとめてみた

# 概要
最近バックエンドからフロントエンドになり、「CSSアーキテクチャについてお勉強してみよう！」ということで、一旦代表的なものをまとめてみました。

# CSSアーキテクチャとは
* cssの設計方法
* 命名規則やディレクトリ構成や色々ある
* 汎用性を持たせる設計をするために、誰がみても、途中で誰が入っても構成等がわかるように設計しようねという思想からきてるっぽい

## BEM
### コンセプト
* CSSセレクタの命名規則と言われている
* Block,Element,Modifierの略
    * Block:塊
        * ヘッダー、ナビゲーション、フッターなどのパーツ
        * 独立してる
    * Element:要素
        * 検索ボタン、検索ボックスなどの部品
        * 機能を持っている
    * Modifier:装飾
        * 部品の状態の色等の装飾

### 実例
#### 命名規則
* `block`に対して、`element`と`modifier`をそれぞれ`_(アンダースコア1つ)`・`__(アンダースコア2つ)`・`-(ハイフン1つ)`で繋げてセレクタを作る
* `--(ハイフン2つ)`で繋ぐ`mindBEMding`という書き方もある
* これらを「セパレーター」と呼ぶ
    * セパレーターを使い分けることで、BlockとElementの区切りなのか、Modifierの区切りなのか、それとも...といった判別ができるようになる
        * BlockとElementの区切りは`__(アンダースコア2つ)`
        * Modifierの区切りは`_(アンダースコア1つ)`
        * 単語の区切りは`-(ハイフン1つ)` etc...

* 例：ブロックの中に3つのボタンがあり、真ん中のボタンだけを赤くする場合

    ```test.html
    <div class="test">
        <button class="test__button">テスト</button>
        <button class="test__button_red"テスト赤色</button>
        <button class="test__button">テスト</button>
    </div>
    ```
    
    ```style.css
    .test {
      border: 1px solid #ccc;
      padding: 16px;
      text-align: center;
      background-color: #fafafa;
    }
    .test__button {
      width: 200px;
      padding: 8px 0;
      border: 1px solid #ccc;
    }
    .test__button_red {
      background-color: red;
    }
    ```

### メリット
* 基礎知識があれば、途中で入った人もCSS設計を理解しやすくすぐに作業ができる
* 多くの人が関わり、長期で運用される・メンテナンスが繰り返されるプロジェクト向き
* 汎用性・流用性の高いものができるので、誰でもメンテナンスがしやすい
* コミュニケーションが取りやすい

### デメリット
* class名が冗長になる
    * Elementのclass名にはblock名を含める必要がある等
* セパレーターの使い方を統一してないと死ぬ

## SMACSS
### コンセプト
* Sassを利用することを前提とし、ファイルをモジュールやレイアウトごとに細分化した後にすべてstyle.scssに@importしてコンパイルすることを推奨している
* CSSを以下5つに分割する考え方
    * ベース
        * 要素セレクタ・属性セレクタ・擬似セレクタなど
            * `body`・`a`・`input`等...
    * レイアウト
        * 構成の大枠のものを定義する
            * 例：ヘッダー、フッター、サイドバー等
        * 接頭辞に`.l-`・`.la-`をつける
    * モジュール
        * ページを構成するもの全て
        * 部品ごとのスタイルの指定をする
            * 例：`.logo`・`.tabs`・`.box`・`.list` 等
        * 接頭辞はつけない
    * ステート
        * javascriptで状態を変化させるときのパターン分け
            * クリックしたらどうなるとか
        * クラス名の接頭辞に`is`をつける
    * テーマ
        * テーマの切り替えに関すること
        * bodyに対してテーマ用のクラスを用意する
### 実例

#### ディレクトリ構成例

```
├── style.scss
│
├── base //ベースに関すること
│   ├── _base.scss 
│   └── _mixins.scss
│
├── layout //レイアウトに関すること
│   ├── _top.scss
│   ├── _header.scss
│   └── _footer.scss
│
└── module //モジュールに関すること
    ├── _btn.scss 
    ├── _logo.scss
    └── _nav.scsss
```

#### コード
```_top.scss
.l-test {
    width: 500px;
    height: 100px;
}
```
### メリット
* 1ファイルのコード量が少なくなる
* 接頭辞をつけることで何の要素なのか、どこの要素なのかが分かりやすい
* 役割ごとに分けることで、コードの混在を防ぐことができる

### デメリット
* Sass使わない場合はあまり意味をもたないかもしれない...
* ディレクトリの中にあるファイルが多くなる

## OOCSS
### コンセプト
* オブジェクト指向を取り入れる
* 構造(形をつくるもの)とスキン(見た目)を分けましょうという考え
    * 構造
        * `width`・`height`・`border`等
    * スキン
        * `color`・`border-color`・`background-color`等

### 実例
#### アンチパターン
* 同じプロパティ・値を繰り返し書く
* 構造に関することと見た目に関することを混在して記述
```test.html
<div class="box1">
    <p>赤色を背景にするよ</p>
</div>
<div class="box2">
    <p>青色を背景にするよ</p>
</div>
```

```
.box1 {
 float: left;
 width: 350px;
 background-color: blue;
 color: white;
 text-align: center;
}

.box2 {
 float: left;
 width: 350px;
 background-color: blue;
 color: white;
 text-align: center;
}
```

#### 推奨される書き方
* 共通のクラス名とそれとは別のクラス名を用意する
* 共通のクラスには構造を、別のクラスにはスキンに関することを記述する

```test.html
<div class="box red-box">
    <p>赤色を背景にするよ</p>
</div>
<div class="box blue-box">
    <p>青色を背景にするよ</p>
</div>
```

```style.css
.box { //構造に関すること
 float: left;
 width: 350px;
 text-align: center;
 background-color: white; // デフォルト値
 color: black; // デフォルト値
}
.red-box { //見た目に関すること
 background-color: blue;
 color: white;
}
.blue-box { //見た目に関すること
 background-color: red;
 color: white;
}
```

### メリット
* 繰り返し同じプロパティ・値を書かないので修正が入った場合、修正箇所を少なくすることができる
* 共通化することでCSSのコードの量を減らすことができる

### デメリット
* コードが複雑になる
* 設計思想を理解するのに時間がかかる

## ECSS
### コンセプト
* OOCSSが繰り返しを許容しないのに対し、ECSSは繰り返しを許容し、適切に分離することを目指す
* 一番大きいものを探して、その中にどんな要素が必要なのか考える
* 特定のスコープで分解する
* 命名規則はBEMの恩恵を受けている
    * 名前空間
        * 接頭辞でコンテキスト・モジュールを表す
    * モジュール
        * BEMでいう`Block`
        * 上位のDOM
    * コンポーネント
        * BEMでいう`Block`
        * 親のDOMに内包される要素
    * 子ノード
        * BEMでいう`Element`
    * バリアント
        * BEMでいう`Modifier`

### 実例

#### 命名規則
* 名前空間に`-(ハイフン1つ)`を足して、接頭辞として使う
* 名前空間とバリアントはローワーキャメルケース
    * `namespace`・`variant`
* 上記以外はアッパーキャメルケース
    * `ModuleName`・`ChildNode`

全て書くと以下のような形

```
namespace-ModuleName_ChildNode-variant
namespace-ComponentName_ChildNode-variant
```

#### ディレクトリ構成
* コンテキストをスコープとしてファイルを管理する
* cssとjsを並列に管理することを推奨
* Namesapce毎にアセットを分けて管理する

例

```
├── Top //Namespace
│   ├── css
│   ├── js
│   └── img
├── Page2 //Namespace
│   ├── css
│   ├── js
│   └── img
├── Page3 //Namespace
│   ├── css
│   ├── js
│   └── img
└── Page4 //Namespace
    ├── css
    ├── js
    └── img
```

### メリット
* Namespaceごとに管理できるので、不要になったときに消しやすいし、必要になったときに追加しやすい。
* 新規ページで似たようなページを作る際既存のページに影響が出づらい

### デメリット
* 同じCSSをひたすら量産し続けるので、ファイル量が膨大になる

## Atomic Design(おまけ)
* ⚠️コメントでも頂いておりますが、Atomic  DesignはCSSアーキテクチャではありません。この記事を書くときに筆者の理解が浅くココに記載してしまいました。申し訳ございません。⚠️

### コンセプト
* ページ単位ではなく、コンポーネント単位でデザインカンプを作る考え方
* コンポーネント同士の組み合わせでページを作る
* 小さいものから少しずつ大きく
* コンポーネントは以下の5つからなる
    * 原子(Atoms)
        * それ以上分割できない要素の単位
            * 例：入力フォーム・ボタンなど
    * 分子(Molecules)
        * 原子を2つ以上組み合わせたもの
            * 例：検索フォーム(入力フォーム + 検索ボタン)
    * 有機体(Organisms)
        * 複数の分子を組み合わせたもの
            * 例：ヘッダー・フッターなど
    * テンプレート(Templates)
        * 有機体を組み合わせたもの
        * 画像や文言等のデータが入っていない
            * 例：ワイヤーフレーム
    * ページ(Pages)
        * テンプレートに画像や文言等のデータを入れたもの
### 実例
* Abema TV
    * 以下URL15ページ目から
[Atomic Design powered by React @ AbemaTV](https://www.slideshare.net/ygoto3q/atomic-desigin-powered-by-react-abematv)

### メリット
* 最小単位まで細分化されているので、修正をしやすい
* 共通化しているので、デザイン変更に対応しやすくなる
* シンプルな構造になっているので、デザインが統一されやすい

### デメリット
* 既存のページが細分化されていなかった場合にAtomic designを途中から導入するにはコストがかかる

## 参考資料
[CSSを長生きさせるための設計手法まとめ（*ECSSあり）](https://qiita.com/mom0tomo/items/ec20486f84c2ede98d9b)
[SMACSSによるCSSの設計第1回 ベースとレイアウト](https://app.codegrid.net/entry/smacss-1)
[知っておきたいHTMLテンプレート設計法第1回 OOCSSの基本](https://app.codegrid.net/entry/oocss-1)
[BEMによるフロントエンドの設計第1回 基本概念とルール](https://app.codegrid.net/entry/bem-basic-1)