【CSS設計思想】駆け出しエンジニアがCSS設計を理解するまで vol.1

新しく入社した会社でしばらくフロントエンドを触っていく事となりました30代半ばの駆け出しエンジニアheyheyです。

フロントエンドを担当するにあたりCSSのより深い理解の為、CSSの設計思想について調べた事をアウトプットしていきたいと思います。

##CSS設計思想とは？

学習している時は何気なく書いていたCSS。企業に入り、大人数で大規模な開発をしていると細かい修正も日常茶飯事。そんな中で修正の度にCSSが崩れては直すを繰り返していたら時間はいくらあっても足りません！

それを防ぐ為にはCSSもしっかりと設計をして開発を始める必要があります。開発しているものや使用言語によっても設計は様々。そうやって生まれたのが多くのCSS設計思想です！

簡単に言ってしまえば、ディレクトリ構成と命名規則の様々な流儀。それでも全ての設計思想は下記の４つのポイントを如何に向上させるかという事を考えて考案されてきました。

- 予測しやすい(可読性)
- 再利用しやすい(再利用性)
- 保守しやすい(メンテナンス性)
- 拡張しやすい(拡張性)


今回はその中でも弊社で参考にしているFLOCSSとそれの元となったOOCSS, BEM, SMACSSを見ていきたいと思います。


##OOCSS

Object Oriented CSSと呼ばれ、オブジェクト指向に基づいて考案された設計思想。TwitterやGithubなどで採用されており、Bootstrapがこの思想のもとに設計されている。パーツパーツの再利用性を上げ、レゴの様に積み上げていく設計。

###原則：
1. 構造(Structure)とスキン(Skin/見た目)を分けて考える
2. コンテナ(Container)と内容(Contents)を分けて考える

###構造とスキンの分離とは
まず**構造**とはwidth, height, border, padding, margin など形を作るモノ。一方、**スキン**はcolor, border-color, background-colorなど見た目のスタイルを司るモノです。

構造をスキンと分離する事で、同じ形だけど違う色のボタンなど再利用しやすくなります。

###コンテナとコンテンツの分離とは
**コンテナ**と**コンテンツ**とは箱とその中身です。グリッドレイアウトなどを想像すると分かりやすいかと思います。コンテナにはコンテナの、コンテンツにはコンテンツのCSSを別々に定義します。スタイルの適用では要素指定を行わず、クラスでの指定のみを行います。

こうする事でHTMLの構造に依存せず、構造に変化があってもCSSの修正が不要になります。これによりCSSのメンテナンス性が向上します。

```html:html
<h1>OOCSS(Object Oriented CSS)</h1>
<ul class="menu">
     <li class="item item-large">link</li>
     <li class="item item-active">active</li>
</ul>
```

```css:css
.menu {
 list-style-type: none;
}
.item {
 width: 80px;
 margin-bottom: 5px;
 color: #4486F7;
 border: 1px solid #4486F7;
 text-align: center;
}
.item-large {
 width: 100px;
}
.item-active {
 color: #fff;
 background-color: #4486F7;
}
```

##BEM

Block Element Modifierの頭文字を取った設計思想で、独特な命名規則を用いる事で有名です。

OOCSSはマルチクラス(要素に対して複数のクラスを使う)に対し、BEMはシングルクラスでスタイルを適用させます。

###原則：
1. Block(塊), Element(要素), Modifier(修飾)の３つに分ける
2. 命名規則.block__element—modifierに則る

###Block, Element, Modifier
**Block**：ヘッダー、ナビゲーション、フッターなど独立したパーツ
**Element**：Blockの中に含まれる様な検索ボタン、検索フィールドなど機能を持つパーツ
**Modifier**:：BlockにもElementにも適用される装飾

###命名規則 
**MindBEMding**という独特の命名規則を採用。基本的にはBlockとElementを2重アンダースコアで、ElementとModifierを2重ハイフンで区切る。これによりその要素がどのBlockに属するのかが一目瞭然となり可読性が上がります。

```html:html
<h1>BEM(Block__Element--Modifier)</h1>
<div class="test">
   <button class="test__button">テスト</button>
   <button class="test__button_red"テスト赤色</button>
   <button class="test__button">テスト</button>
</div>
```
```css: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;
}
```

##SMACSS

Scalable and Modular Architecture for CSSの略で、OOCSSやBEMの流れを汲んで生まれた設計思想です。OOCSS同様マルチクラスでスタイルの適用をします。

###原則：
1. スタイルをBase、Layout、Module、State、Themeの５つに分割する
2. 一部クラスに接頭辞(プレフィックス)を付ける

###Base, Layout, Module, State, Theme

**Base**：要素セレクタ・属性セレクタ・擬似セレクタなどに対して適用するスタイルを指定。CSSリセットなどもこちらに含まれます。
ex. `body`・`a`・`input`...

**Layout**：ヘッダー、フッター、サイドバーなど構成の大枠のものを定義。接頭辞に`.l-`や`.la-`を付ける。

**Module**：ページを構成する再利用可能なパーツごとのスタイルを指定。接頭辞は付けないので頭に何も付いていないクラスがあれば、それはモジュールという事。

**State(状態)**：Javascriptで状態を変化させる時のパターン分けなどを定義。接頭辞に`.is-`を付ける。
ex. `.is-disabled`・`.is-active`・`.is-error`など

**Theme(テーマ)**：レイアウトやモジュールなど全体のテーマカラーを変更したい場合に使用。接頭辞に`.theme-`を付ける。

SMACSSはSassを利用する事を前提としており、ファイルを細分化した後に全てstyle.scssに＠importしてコンパイルする事を推奨しています。

```html:html
h1>SMACSS(Scalable and Modular Architecture for CSS)</h1>
<div class="l-container">
 <ul class="menu">
   <li class="menu-item is-large">link</li>
   <li class="menu-item is-active">active</li>
 </ul>
</div>
```
```css:css
.l-container { /***/ }
.menu {
 list-style-type: none;
}
.menu-item {
 width: 80px;
 margin-bottom: 5px;
 color: #4486F7;
 border: 1px solid #4486F7;
 text-align: center;
}
.is-large {
 width: 100px;
}
.is-active {
 color: #fff;
 background-color: #4486F7;
}
```

##FLOCSS

Foundation Layout Object CSSの略。OOCSSやSMACSS、BEMなどのコンセプトを取り入れた設計思想で、SMACSSの様なレイヤー構成とBEMの命名規則を採用しています。こちらもマルチクラスでスタイルを適用させます。

###原則：
1. Foundation, Layout, Objectの３つのレイヤーとObject下のComponent, Project, Utilityの３つの子レイヤーで構成される。
2. MindBEMdingの命名規則を用いる。
3. Objectには接頭辞(プレフィックス)を付ける

###Foundation, Layout
**Foundation**：Reset.cssやNormalize.cssなどブラウザのデフォルトスタイルの初期化やプロジェクトの基本的なスタイルを定義。

**Layout**：ヘッダーやメインのコンテンツエリア、サイドバー、フッターなどプロジェクト共通のコンテナブロックのスタイルを定義。

###Object(Component, Project, Utility)
**Component**：再利用できる小さい単位のパーツを定義。接頭辞に`.c-`を付ける。

**Project**：いつかのcomponentとそれに該当しない要素によって構成される集合体。接頭辞に`.p-`を付ける。ex. 記事一覧、ユーザープロフィール、画像ギャラリーなどのコンテンツ。

**Utility**：componetやProjectレイヤーの定義では解決出来ないわずかなスタイルの調整などに用いる汎用クラスで単一のスタイルだけを定義したモノ。接頭辞に`.u-`を付ける。

###※ComponentとProjectの違い
何を最小単位(component)とするかは人によって異なり、時にCSSを破綻させる原因ともなります。そういった際の分かりやすい分類の例としてPowerpointの図形とグループが挙げられます。
`component`：パワポの図形１つの単位
`project`：グループ化して動かす単位

https://qiita.com/uggds/items/d904b2f9a103c37a25fa

###Objectの命名規則
BEM同様Block__Element—Modifierの規則に則って命名する。唯一JavaScriptで操作される様な「状態」に付いてはSMACSSのStateパターン同様の`.is-`を接頭辞に付ける。ex. `.is-active`

```html:html
<h1>FLOCSS</h1>
<div id="container">
 <ul class="o-menu">
   <li class="c-item c-item--large">link</li>
   <li class="c-item c-item--active">active</li>
 </ul>
</div>
```
```css:css
.flocss {
 #container { /***/ }
 .o-menu {
   list-style-type: none;
 }
 .c-item {
   width: 80px;
   margin-bottom: 5px;
   color: #4486F7;
   border: 1px solid #4486F7;
   text-align: center;
 }
 .c-item--large {
   width: 100px;
 }
 .c-item--active {
   color: #fff;
   background-color: #4486F7;
 }
}
```

##まとめ
以上、なるべくどの設計思想がどの設計思想に影響を受けて生まれたか分かりやすい様にOOCSS→BEM→SMACSS→FLOCSSという順番でご紹介させて頂きました。

しかしSMACSSやFLOCSSはSassやScssを使う事を前提にした設計思想でもあり、設計思想単体での説明では分かりにくい所もあるかと思います。

という事で次回はこれらの設計思想も絡ませつつ、SassとScssを見ていきたいと思います。

それではまた！