2017/03/21

OOCSS、BEM、SMACSS、FLOCSS、RSCSSを比較して自分にあった設計思想をみつける

フロントエンドエンジニアというポジションに就いて1年半、普段はJavaScriptを中心に開発している。しかし、いつまで経ってもCSSを思いどおりに使いこなせない。理由は、どんな粒度でクラスを分割し、それぞれにどんなスタイルを適用すれば良いのかわからないからだ。

以下が、CSSの闇にのまれ、筋肉に解決に糸口を見出そうとした哀れなフロントエンドエンジニアの心の叫びだ。

ということで、よく話題にされる5つのCSS設計を比較し、自分にあった設計思想を見つけようと思う。(CSSは苦手なので、おかしな点があったらご指摘ください)


今回比較するCSS設計思想は以下の5つ。
  • OOCSS
  • BEM
  • SMACSS
  • FLOCSS
  • RSCSS


古代のCSS設計


まずはCSSの設計思想に触れる前に、いにしえより伝わりしCSS遺産について触れておく。
多くの場合はIDセレクタを使い、要素ひとつずつに対してスタイルを指定する。
<!-- legacy.html -->
<h1>Ancient Legacy</h1>
<ul id="menu">
  <li id="large-item">link</li>
  <li id="active-item">active</li>
</ul>
/* legacy.css */
#menu {
  list-style-type: none;
}
#large-item {
  width: 100px;
  margin-bottom: 5px;
  color: #4486F7;
  border: 1px solid #4486F7;
  text-align: center;
}
#active-item {
  width: 100px;
  margin-bottom: 5px;
  color: #fff;
  background-color: #4486F7;
  border: 1px solid #4486F7;
  text-align: center;
}
私にはメンテできる自信がない。ツラそう。



OOCSS


OOCSS(Object Oriented CSS)は、オブジェクト指向にもとづいて考案された設計思想。TwitterやGitHubなどで採用されており、身近なところでいうとBootstrapがこの思想のもとに設計されている。

特徴

  • Container(入れ物)とContents(中身)を分けて考える
    • .container > .contentsのように依存関係にせず、.containerと.contentsを独立させる(再利用性が向上)
  • Structure(基本構造)とSkin(見た目)を分けて考える
    • .btnで基本構造を定義し、.btn-primaryで見た目を変更する

サンプルコード

<!-- oocss.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>
/*oocss.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;
}

感想

「レゴのように考える」という思想で、オブジェクト指向を理解している人には入門しやすい。Bootstrapでも使われているので馴染みもある。
ただ、フレームワークのようにキッチリ設計されたものは良いけど、自らこの思想に則ってコーディングするのはちょっと難しそう。



BEM


BEM(Block Element Modifier)は、独特な命名規則(MindBEMding)で有名な設計思想。OOCSSはマルチクラス(クラスを組み合わせて使う)のに対し、BEMはシングルクラス(ひとつのクラスで定義する)なのでメンテがしやすい。

特徴

  • Block
    • もととなる要素
  • Element
    • Block内にある子要素
  • Modifier
    • 変化した状態を表す要素

3つをBlock__Element--Modifierのように結合してクラス名を決める。
Elementはアンダースコア2つ(__)で結合、Modifierはダッシュ2つ(--)で結合する。

サンプルコード

<!-- bem.html -->
<h1>BEM(Block__Element--Modifier)</h1>
<ul class="menu">
  <li class="menu__item--large">link</li>
  <li class="menu__item--active">active</li>
</ul>
/* bem.sass */
.menu {
  list-style-type: none;
}
.menu__item {
  width: 80px;
  margin-bottom: 5px;
  color: #4486F7;
  border: 1px solid #4486F7;
  text-align: center;
}
.menu__item--large {
  @extend .menu__item;
  width: 100px;
}
.menu__item--active {
  @extend .menu__item;
  color: #fff;
  background-color: #4486F7;
}

感想

第一印象はキモい。クラス名がやたら長くなり、慣れるまでは拒否反応を示すくらいだった。
でも、実際使っていくとシングルクラスなのでHTMLとCSSを対比しやすく、メンテしやすい印象がある。



SMACSS


SMACSS(Scalable and Modular Architecture for CSS)は、OOCSSやBEMの流れをうけて考案された設計思想。

特徴

  • Base
    • reset.cssやnormalize.css
    • サイト全体のデフォルトスタイルを定義する
  • Layout
    • Moduleの配置を決める
    • プレフィックスに「l-」をつける(例: .l-main、.l-sub)
  • Module
    • 再利用可能なパーツ
    • 親モジュールの名前をプレフィックスにつける(例: 親: .item、子: .item-box)
  • State
    • LayoutやModuleの変化した状態
    • プレフィックスに「is-」をつける(例: .is-active、.is-error)
  • Theme
    • LayoutやModuleのTheme(色を管理する)
    • プレフィックスに「theme-」をつける(例: .theme-color)

サンプルコード

<!-- smacss.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>
/* smacss.sass */
.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;
}

感想

OOCSSをより役割ごとに分割したような設計思想で、スッキリしていてわかりやすい。
実際に使ったことはないが、BEMよりメンテがしやすそう。



FLOCSS


FLOCSS(たぶんFoundation Layout Object CSS)は、OOCSSやBEM、SMACSSの流れを受けて考案された設計思想。

特徴

  • Foundation
    • reset.cssやnormalize.css
    • サイト全体のデフォルトスタイルを定義する
  • Layout
    • Objectの配置を決める
    • ページ単位で唯一の存在になるのでidセレクタを使う
  • Object
    • Component
      • 再利用可能なパーツ
      • プレフィックスに「c-」をつける(例: .c-btn、.c-btn_primary)
    • Project
      • Componentにするほどでもないパーツ
      • プレフィックスに「p-」をつける(例: .p-article、p.article__title)
    • Utility
      • 汎用クラスで単一のスタイルを持つ
      • プレフィックスに「u-」をつける(例: .u-clearfix、.u-block)

BEMとおなじMindBEMdingという命名規則が用いられている。
また、ディレクトリ構成も構造に合わせて分割することで、メンテしやすくなっている。
├── foundation
│   ├── _base.scss
│   └── _reset.scss
├── layout
│   ├── _main.scss
│   └── _sidebar.scss
└── object
    ├── component
    │   ├── _button.scss
    │   └── _grid.scss
    ├── project
    │   ├── _articles.scss
    │   └── _profile.scss
    └── utility
        ├── _clearfix.scss
        ├── _margin.scss
        └── _text.scss

サンプルコード

<!-- flocss.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>
/* flocss.sass */
.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;
  }
}

感想

CSSのメタ言語必須なCSS設計。参考にしたとされるOOCSSやBEM、SMACSSのいいとこ取りをしている印象。小さなページには大きすぎる設計思想な気もするけど、ディレクトリ含め構造化されているのでチーム開発のときに本領が発揮されそう。



RSCSS


RSCSS(Reasonable System for CSS)は、SMACSSやFLOCSSとくらべて小さいルールで、設計思想もちょっと違う。

特徴

  • Components
    • 再利用可能なパーツ
    • ダッシュで区切った少なくとも2単語からなる(例: .search-form, .article-card)
    • 再利用するためにポジションに関するプロパティはLayoutにまとめる(positionやfloat、marginなど)
  • Elements
    • Componentsを構成する要素
    • 1単語にする(例: .search-form > .field, .search-form > .action)
    • 複数単語を使いたい場合は、ダッシュやアンダースコアを使わず単純に結合する(例: .firstname、.lastname)
    • タグセレクタは使わない
  • Variant
    • 変化した状態を表す要素
    • プレフィックスにダッシュをつける(例: .-wide、.-active)
  • Layout
    • Componentsの配置を決める
  • Helpers
    • 値を上書きするときに使う
    • プレフィックスにアンダースコアをつける(例: ._unmargine、._center)

CSSを書くときにできるかぎり子セレクタ(>)を使う。子孫セレクタは使っても良い。
依存関係をあえてつくることで、短いクラス名も使えるようになる。

サンプルコード

<!-- rscss.html -->
<h1>RSCSS(Reasonable System for CSS Stylesheet Structure)</h1>
<ul class="menu-list">
  <li class="item -large">link</li>
  <li class="item -active">active</li>
</ul>
/* rscss.sass */
.menu-list {
  & {
    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;   
  }
}

感想

最近知ったCSS設計思想だが、シンプルでわかりやすい。個人的にはこの5つの思想の中で一番シックリきたものだった。
Vue.jsでvueファイルをコンポーネントごとにわけ、scopedを付けてスタイリングしているので、rscssがあっている気がする。



各CSS設計思想の対比表


OOCSSBEMSMACSSFLOCSSRSCSS
??BaseFoundation?
Container?LayoutLayoutLayout
StructureBlockModuleObject-ComponentComponents
SkinModifierStateComponentVariant
??ThemeProject?
???UtillityHelpers


以上

written by @bc_rikko

0 件のコメント :

コメントを投稿