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

CSSの設計方法をまとめてみた~SUIT CCS編~

SUIT CSSについて、簡単にまとめる。
また、Angularを使用した簡単なサンプルも書いてみる。
なお、本記事は、公式ドキュメントをかなり参考にさせていただいている。

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

SUIT CSSとは

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

SUIT CSSのメリット

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

SUIT CSS の設計原則

ここで使用している英文は以下から引用させていただいている。
suit/design-principles.md at master · suitcss/suit

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、CSSJavaScriptを含んでいる。

=> 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 で記述する。
utilityNamecamel caseで記述する。
レスポンシブデザインを考慮した書き方もでき、その場合は 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(アッパーキャメルケース)で記述する。
<div class="ComponentName">hoge<div> という形で記述する。
.ComponentName{...} という形でstyleを適用する。

ComponentName--modifierName

ベースとなるComponentの表現を変更するためのclass。
camel caseで記述する。
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で記述する。
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

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

<!--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

/*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

@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

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

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

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

実装結果

クリック前
suitccs-before-click.png

クリック後

suitccs-after-click.png

関連記事

CSSの設計方法をまとめてみた~BEM編~ - Qiita

所感

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

参考にさせていただいたサイト

suit/doc at master · suitcss/suit

キャメルケース - Wikipedia

HTML5のお勉強 articleとsectionとか - Qiita

[HTML5] 新要素まとめ【2014/2/14版勧告候補】 - Qiita

Qiitaでも同一の投稿を行っている。