CSSの設計方法をまとめてみた~SUIT CCS編~(Angularによるサンプル付き)

# CSSの設計方法をまとめてみた~SUIT CCS編~
SUIT CSSについて、簡単にまとめる。
また、Angularを使用した簡単なサンプルも書いてみる。
なお、本記事は、[公式ドキュメント](https://github.com/suitcss/suit/tree/master/doc)をかなり参考にさせていただいている。

詳細な部分に関しては以下の記事がわかりやすかったので、参考にされると良いと思う。
[suit/design-principles.md at master · suitcss/suit](https://github.com/suitcss/suit/blob/master/doc/design-principles.md)
[suit/naming-conventions.md at master · suitcss/suit](https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md)

## SUIT CSSとは
Componentベースのcssの方法論。
Componentベースなので、AngularやReactなどのComponent指向なJavaScriptフレームワークやライブラリと相性が良いそう。

## SUIT CSSのメリット
各々のユニットの結びつきを緩くして、独立したものにすることができる。

## SUIT CSS の設計原則
ここで使用している英文は以下から引用させていただいている。
[suit/design-principles.md at master · suitcss/suit](https://github.com/suitcss/suit/blob/master/doc/design-principles.md#modularity)

### Modularity(モジュール性)
> Each component should have a single focus and contain everything necessary to realise a specific part of the UI. 

【意訳】
各Componentは、1つの事柄に集中して、また、UIの特定のパーツを実現するのに必要なすべてのものを含んでいるべきである。

Componentは、HTML、CSS、JavaScriptを含んでいる。

=> AngularのComponentのようなもの。

### Cohesion(結束)

> The functionality and presentation defined by a component must be semantically related. Components do not have direct influence over each other.

【意訳】
Componentによって、定義される機能性と表現は、意味的に結びついていなければならない。
Componentは、違いに直接的な影響を与えない。

### Composable and configurable(組み立て可能で、設定可能である)
必要に応じて、Componentを組み合わせ可能であること。

> Configuration is done via interfaces that are provided and used by components.

【意訳】
Componentによって提供され、利用されるinterfaceを通して、設定が行われる。
    
### Loose coupling(弱い結びつき)
Component間の依存関係は、直接Component同士であれこれするのではなく、interfaceとeventでどうにかしましょう。

### Soft encapsulation(ソフトなカプセル化)
Componentを他のComponentからカプセル化して、他のComponentから直接Component内のコードを利用できなくする必要がある。

### Documentation(文書化)
各Componentの役割やCSSプロパティがなぜ必要かを丁寧に文書化する。

## SUIT CSS の命名規則
SUIT CSSでは、意味のあるハイフンと構造化したclassを使用する。
SUIT CSSでは、大きく分けて、UtilitiesとComponentsと概念が存在する。
繰り返し使うようなCSSのプロパティに対して、適用すると何回もCSSを記述しなくても良くなる。

### Utilities
Utilitiesは、低レベルの構造的また位置の特徴を表す。
Componentの中で、どの要素にも直接適用できる。
繰り返し使うようなCSSのプロパティに対して、適用すると何回もCSSを記述しなくても良くなる。

#### 記述方法
基本的には `u-utilityName` で記述する。
`utilityName` は[camel case](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9)で記述する。
レスポンシブデザインを考慮した書き方もでき、その場合は `u-size-utilityName` で記述する。
sizeは `sm` = small、 `md` = medium、 `lg` = large Mediaのいずれかを適用する。


#### 記述例
以下のように記述する。

```
<p class="u-floatLeft">hoge</p>
```

### Components
#### 記述方法
`namespace-ComponentName-descendentName--modifierName` というふうに記述する。

##### namespace(任意)
必要に応じて、namespaceというプレフィックスをつけることができる。
これによって、自作の部分とライブラリの区別がつきやすくなったりする。
`<div class="namespace-Component">hoge<div>` という形で記述する。
`.namespace-Component{...}` という形でstyleを適用する。

##### ComponentName
Componentの名前。
[pascal case(アッパーキャメルケース)](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9)で記述する。
`<div class="ComponentName">hoge<div>` という形で記述する。
`.ComponentName{...}` という形でstyleを適用する。


##### ComponentName--modifierName
ベースとなるComponentの表現を変更するためのclass。
[camel case](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9)で記述する。
ComponentName--modifierNameは、ベースとなるに追加してHTML上に書く。
`<div class="ComponentName ComponentName--modifierName">hoge<div>` という形で記述する。
以下の形でstyleを適用する。

```
.ComponentName{...}
.ComponentName--modifierName{...}
``` 


##### ComponentName-descendentName
Componentの子要素のようなもの。
Componentの子要素に直接、cssの表現を適用する。
`<div class="ComponentName-descendentName">hoge<div>` という形で記述する。
`.ComponentName-descendentName{...}` という形でstyleを適用する。

##### ComponentName.is-stateOfComponent
Componentの状態の変更を反映するのに使用する。
[camel case](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9)で記述する。
state nameはいろんなところで使い回すけども、各Componentによってstateに当てるstyleは異なるので、直接このstate nameにstyleを当ててはいけない。
`<div class="ComponentName is-stateOfComponent">hoge<div>` という形で記述する。
以下の形でstyleを適用する。

```
.Compomnent{}
.Compomnent.is-stateOfComponent{}
``` 
という感じでstyleを適用する。

## 実際に書いてみた
実際にComponent指向のjavaScriptフレームワークであるAngularで実装してみた。

### 実際のコード

app.component.ts

```ts
import {Component} from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss', './utilities.scss']
})
export class AppComponent {
  contentsTitle = 'SUIT CSS!';
  contentsHeading = 'design principles';
  designPrinciples = ['Modularity', 'Cohesion', 'Composition and configuration', 'Loose coupling', 'Soft encapsulation', 'Documentation'];
  clazz = 'AppComponent is-coloredBlack';

  /**
   * 文字を赤くする
   */
  changeColorToRed() {
    this.clazz = 'AppComponent is-coloredRed';
  }

}

```

app.component.html

```html

<!--Component Name-->
<article class="AppComponent">
  <!--ComponentName-descendentName-->
  <header class="AppComponent-header">
    <h1>{{contentsTitle}}</h1>
  </header>
  <!--ComponentName-descendentName-->
  <div class="AppComponent-content">
    <!--ComponentName.is-stateOfComponent-->
    <h1 [class]="clazz" (click)="changeColorToRed()">{{contentsHeading}}</h1>
    <!--utilities-->
    <ul class=" u-listStyleNone">
      <li *ngFor="let p of designPrinciples">
        {{p}}
      </li>
    </ul>
  </div>
</article>
```

app.component.scss

```scss

/*AppComponentに対するstyle*/
.AppComponent {
  width: 100%;
  .AppComponent-header {
    color: #0000ed;
  }
  .AppComponent-content {
    color: #3A3A3A;
  }
  .is-coloredBlack {
    color: black;
  }
  .is-coloredRed {
    color: red;
  }
}
```

app.component.scssからemitされたapp.component.css

```css

@charset "UTF-8";
/*AppComponentに対するstyle*/
.AppComponent {
  width: 100%;
}

.AppComponent .AppComponent-header {
  color: #0000ed;
}

.AppComponent .AppComponent-content {
  color: #3A3A3A;
}

.AppComponent .is-coloredBlack {
  color: black;
}

.AppComponent.is-coloredRed {
  color: red;
}
```

utilities.scss 

```scss 
/*listの点を消す*/
.u-listStyleNone {
  list-style: none;
}
```

utilities.scssからemitされたutilities.css 

```css
@charset "UTF-8";
/*listの点を消す*/
.u-listStyleNone {
  list-style: none;
}
```

### 実装結果

クリック前
![suitccs-before-click.png](https://qiita-image-store.s3.amazonaws.com/0/145611/1d299245-8263-75bf-99b0-f77f2cb1c649.png)

クリック後

![suitccs-after-click.png](https://qiita-image-store.s3.amazonaws.com/0/145611/29e68278-ab32-683d-fccf-7e399b278e18.png)

## 関連記事
[CSSの設計方法をまとめてみた~BEM編~ - Qiita](https://qiita.com/Sekky0905/items/c1fc597adab5a77b0ce6)

## 所感
Component指向が根底にある設計方法なので、Angularなどの現代的なComponentベースのフレームワークと相性がよくて、使いやすそう。
Component指向のフレームワークを使っている人にはすごく馴染みやすいと思う。
また、システマチックな感じに考えられているところがよかった。


## 参考にさせていただいたサイト
[suit/doc at master · suitcss/suit](https://github.com/suitcss/suit/tree/master/doc)

[キャメルケース - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9)

[HTML5のお勉強　articleとsectionとか - Qiita](https://qiita.com/piotzkhider/items/faffbc4a107e7e495998)

[[HTML5] 新要素まとめ【2014/2/14版勧告候補】 - Qiita](https://qiita.com/maccotsan/items/20c6ea274b0190dc2c05)

※ [ブログ](http://sekky0905.hatenablog.com/entry/2017/09/21/CSS%E3%81%AE%E8%A8%AD%E8%A8%88%E6%96%B9%E6%B3%95%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E3%81%BF%E3%81%9F~SUIT_CCS%E7%B7%A8~%28Angular%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B5%E3%83%B3%E3%83%97)でも同一の投稿を行っている。