CSSを長生きさせるための設計手法まとめ(*ECSSあり)

  • 20
    いいね
  • 0
    コメント

CSSの設計手法については、数年前からたくさんのブログや書籍で詳細に取り上げられており、コーディングを業務とする人には周知のことと思います。

そんな中で改めてまとめるのは恐縮なのですが、今回はDip株式会社アドベントカレンダーということで、バックエンドからフロントエンドに来られたエンジニアさんや、コーディングに知識のあるディレクター・企画職の方にナレッジが共有できたらなと思い書いてみました。

OOCSS,SMACS,BEMといった定番たちに加え、今年になって徐々に知られ始めたECSSについても取り上げています。

なぜCSS設計が必要なのか

mizuno hayatoさんのなんでCSSすぐ死んでしまうん?のスライドは有名ですが、CSSは単純で多くの人が簡単に操作することができるという素晴らしい特性を持ち合わせているがために、複数人の関わる大規模なプロジェクトや、長期的なメンテナンスが必要なプロジェクトではすぐに破綻してしまうという弱点を抱えています。
複数人が関わり、長期に渡ってメンテナンスされるプロジェクトに参加するコーダーにとって、自分以外の人でも容易に理解できてメンテナンスしやすい設計を行う能力は大変重要です。また、複数の設計手法の知識を持つことで、慣れ親しんだ設計手法と異なるものが採用されているプロジェクトに途中から参加した際にも、すぐに理解して戦力になることができます。

以下では4つのCSSの設計手法を取り上げていきます。

OOCSS

Object Oriented CSS
⭐️コーダー利用率:15.7% *

概要

・オブジェクト指向をCSSに取り入れる
・構造とスキン(見た目)を分離する
・コンテナと内容を分離する

構造とスキン(見た目)の分離

Webサイトには必ずある、ボタンを例にして考えます。

構造とは、ボタンの形を作るものです。
width,height,border,padding,margin
などにあたります。

そしてスキンとは見た目、スタイルになります。
color,border-color,background-color
などです。

構造をスキンと分離することで、機能によって色が違うボタンを作ったり、それをサイト全体で再利用したりするのが簡単で便利になります。

/* 構造 */
.btn {
    width: 100px;
    height: 20px;
    line-height: 1.5;
    text-align: center;
}
/* スキン */
.btn-caution {
    background-color: red;
}
.btn-submit{
    background-color: green;
}
.btn-plane{
    background-color: gray;
}

<a class="btn btn-caution">注意ボタン</a>
<a class="btn btn-submit">送信ボタン</a>
<a class="btn btn-plane">普通のボタン</a>

コンテナと内容の分離

HTML要素や構造、コンポーネントが存在する「場所」に依存しないようにします。
webサイトによくある見出しを例に考えます。

ヘッダー内にある見出しにスタイルを当てるとき、下記のようにすると、他のsectionにも同じ見出しを入れたい...という時に再利用できなくなります。

.header .heading {
    font-size: 18px;
    font-weight: bold;
    text-align: center;
    color: red;
}

このため、OOCSSでは以下のようにコンテナにclassをつけてスタイルを当てることが推奨されます。

.heading {
    font-size: 18px;
    text-align: center;
}

.heading .heading-big {
    color: red;
    font-weight: bold;
}

これで、他のsectionに見出しをいれたいときはdivタグなどを置いて.heading .heading-bigというclassを当てるだけでスタイルを流用することができます。

ディレクトリ構成の例


├── common
│  ├── css ── common.css
│  ├── img
│  └── js
│ 
└── page
    ├── css 
    │   ├── p01.css
    │   └── p02.css
    ├── img
    └── js


メリット

使えるものはどんどん共通化することで、CSSのコード量を減らせます。

デメリット

コードが複雑になります。共通化によってどこにどのスタイルが当たるのか、CSSの見通しは悪くなることがあります。
特に、CSSファイルの切り分けがうまくできていなかったり、どのパーツが共通化されているのかわかるガイドがない場合、新しくプロジェクトに参加するメンバーは初めに時間をかけてコードを読み、苦心して設計思想を理解することになります。

SMACSS

Scalable and Modular Architecture for CSS
⭐️コーダー利用率:14.7%

概要

・スタイルをベース、レイアウト、モジュール、ステート、テーマの5つに分割する
・レイアウトにはlayout-, .l- などの接頭辞をつける
・ステートにはis- 接頭辞をつける
・テーマにはtheme- 接頭辞をつける
・モジュールにはmod-, m-などの接頭辞はつけない

ベース

要素セレクタbody、liなど、属性セレクタinput[type=button]など、擬似クラスセレクタa:hoverなどです。セレクタそのもののみが対象で、idはベースには記述しません。
また、CSSリセット(reset.cssやnormalize.cssなど)もベースに含まれます。

レイアウト

セクションやエリアなど、大きな区切りとなる部分を定義します。
(.layout-header, .layout-footer, .layout-nav, .layout-mainなど)

モジュール

部品ごとのスタイルを指定します。(.logo, .tabs, .box, .list, .formなど)
接頭辞をつけないので、「接頭辞がなければモジュール」とすぐに認識することができます。
モジュール内のパーツには全てclassをつける必要はなく、h1,li,aなどは要素セレクタにスタイルを当てても良い

ステート(状態)

JavaScriptで状態を変化させるときのパターン分けなどに使います。
(.is-disabled, .is-active, is-errorなど)

テーマ

あまり利用されません。ページ全体のカラーやテーマなどを選択して変えられるサイトで使います。

ディレクトリ構成の例

├── style.scss
│
├── base
│   ├── _base.scss 
│   └── _mixins.scss
│
├── layout
│   ├── _top.scss
│   ├── _product.scss
│   └── _grid.scss
│
└── module
    ├── _btn.scss 
    ├── _logo.scss
    └── _nav.scsss

SMACSSはSassの利用を前提とし、ファイルをモジュールやレイアウトごとに細分化した後にすべてstyle.scssに@importしてコンパイルすることを推奨しています。

メリット

コード量が少なくなり、メンテナンス性が向上します。
例えば「ヘッダーのデザインと、submitボタンの色を変えたい」などというとき、どのファイルを修正すればいいのか一目瞭然です。

デメリット

生のCSSのみを使うプロジェクトでは、ファイルを切り分けてメンテナンス性を向上させるという恩恵が受けられません。

BEM

Block Element Modifier
⭐️コーダー利用率:38.4%

概要

・Block(塊)、Element (要素)、Modifier (修飾) の3つに分ける
・命名規則は.block--element__modifierとする
・原則としてスタイルは全てclassに当てる
・Elementのclass名には必ずBlock名を含める

Block

ヘッダー、ナビゲーション、記事、フッター、リストなどの大きなパーツです。

Element

ナビゲーション(パーツ)の中の検索ボタン、検索フィールドなどの部品です。

Modifier

Blockにも、Elementにも適用されます。
ボタン(部品)のエラー状態と通常状態の色、記事(パーツ)の囲みがあるものとないものなど、装飾を表します。

メリット

メンテナンスやチームでの作業に適しています。BEMは一目見ればすぐにでそのタグがどこのブロックに属しているかがわかるので、別ページのHTMLをコピーして同じスタイルを当てたい時などに大変重宝します。再利用性が高い設計手法です。
また現状もっとも普及している手法なので、新しくコーダーがジョインした場合やエンジニアとコーダー、デザイナーが密に協業する場合も、BEM自体の基礎知識を持っていれば、すぐに全員がプロジェクトのCSS設計を理解し、スムーズに対応することができます。

デメリット

一つのclass名が長くなります。ハイフンとアンダースコア、キャメルケースが混在するので、人によってはすごく気持ち悪く見えます。
また、BlockなのかElementなのか判断がつけにくく、BlockとElementに汎用的な名前をつけようとするととても難しいです。

ECSS

Enduring CSS
⭐️コーダー利用率:3.6%

概要

・名前空間、モジュール(コンポーネント)、子ノードにわける
・BEMの影響を強く受けており、モジュール(コンポーネント)がBlock、子ノードがElementにあたる
・名前空間にハイフンを足して、接頭辞として使う
- 例:tp-Carousel(トップページのカルーセル)

名前空間

プログラミングでいうところの名前空間のような感じです。
思わぬところに影響しないよう、スタイルの適用範囲を一定の部分に閉じ込めるために使います。ECSSでは接頭辞をつけています。
ECSSでは汎用的なモジュールを作ることは推奨されませんが、どうしても汎用化したいモジュールについては、st-(Structure)という接頭辞の名前空間が用意されています。

モジュール

BEMのBlockとほぼ同じです。

子ノード

BEMのElementとほぼ同じです。

ディレクトリ構成の例

├── Top
│   ├── css
│   ├── js
│   └── img
├── Page2
│   ├── css
│   ├── js
│   └── img
├── Page3
│   ├── css
│   ├── js
│   └── img
└── Page4
    ├── css
    ├── js
    └── img

メリット

特定の一ページ、一部分のデザインの変更に柔軟で強いCSSを書くことができます。
上位に名前空間があるので、モジュールや子ノードの命名をBEMほどには考えなくても問題がありません。
汎用的にまとめるという考え方がないので、デザイナーがより自由にWebデザインを考えることができます。

デメリット

ECSSはとにかく「分ける」ということを大切にするので、コードが増えます。ボタンのようなサイト全体で何度も出てくる部品も汎用化しないため、同じCSSのコードを何回も書くことになります。
OOCSSのように、ボタンのような汎用的な小さいモジュールを作ることは推奨されていません。変更があった時に修正に時間がかかります。

おまけ:Sass

コーダー利用率:70.6%
OOCSSが広がったのちの2013-2014年頃から使われるようになったCSSプリプロセッサです。

Sassのメリットは冗長になりがちなBEMの記法や、手動では面倒なOOCSSモジュールの継承をネストやmixin,extendによって簡単に実現できることです。

maesblogさんの記事がCSS設計での便利な使い方をわかりやすく解説してくださっています。

最後に

PostCSSについても書きたかったのですが、途中で力尽きました。
説明の粗い部分も多いので、今後も随時書き足していこうと思っています。

参考

⭐️ コーダーの利用率については以下の統計を参考にしています。

コーダー白書

これはCSS Nite のCorder's High 2016というイベントで集計・発表されたもので、私自身も参加したのですが、かなり現場感のあるリアルな統計がまとめられた貴重な資料です。最後のペルソナ設計までとても見応えがあるので、コーダー・マークアップエンジニアやコーダー寄りのフロントエンドエンジニアの方が見ると、きっと面白いかと思います。

この投稿は ディップ Advent Calendar 201612日目の記事です。