CSS設計における3大メソッド[OOCSS][BEM][SMACSS]

CSS設計における3大メソッド[OOCSS][BEM][SMACSS]
こんにちは。マツコです。

突然ですが、CSS設計はとても重要なものです。

一定のルールがないと、コーダー各々が違う考え方でスタイルづけをして余計なCSSが増えてしまったり、本人でなければ分からないルールが発生してしまい、メンテナンスがしにくくなってしまいます。
そのため、以下のことを強く意識してCSS設計を行うことが大切だと言われています。

  • 予測しやすい
  • 再利用しやすい
  • 保守しやすい
  • 拡張しやすい
今回は上記の目的を達成するヒントとなる、著名なCSS設計手法である「OOCSS」「BEM」「SMACSS」についてお話したいと思います。

OOCSS

概要

  • Object Oriented CSS(オブジェクト指向CSS)の略。
  • オブジェクト指向に基づいて、考案された設計手法です。
  • Yahoo!のNicole Sulivan氏によって開発され、Twitter(とBootstrap)やGithub、Youtubeでも使われています。

考え方

構造と見た目、又コンテナと内容を分離してクラス定義し、それらを組み合わせてスタイルを定義する方法です。
IDや子孫セレクタによってスタイルを定義するのではなく、「すべてのスタイルをクラスで定義」して「それらを組み合わせる」ということです。

構造と見た目の分離(Separate structure and skin)

普遍的な構造と、繰り返し定義される見た目は、別に定義するべきという考え方です。
構造と見た目を分離することで、少ないコードでより多くの見た目を定義することができます。

  • 構造…width,height,border,padding,margin等
  • スキン…color,border-color,background-color等

/* ボタンの構造(structure):共通的な構造を指定 */
.btn {
width: 200px;
height: 50px;
line-height: 50px;
text-align: center;
}
/* ボタンの見た目(skin) */
.btn-blue {
background-color: blue;
color: white;
}
基礎となる構造が独立して指定されているので、今後他の色のボタンが追加されても見た目のスタイルを定義するだけで済みますね。


<a class="btn btn-blue">青ボタン</a><br> <a class="btn btn-red">赤ボタン</a><br> <a class="btn btn-gray">グレーボタン</a><br>
サイトのデザインによって、構造とスキンは分け方が変わることはあると思います。
ボタンデザインは角丸(border-radius)を使うと統一されていれば構造に入れ、ボタンにって異なるのであればスキンに入れるなど、サイト構成を把握して柔軟に考える必要が有ります。

コンテナと内容の分離(Separate container and content)

HTML要素や構造、コンポーネントが存在する「場所」に依存しないCSSを実現するための考え方です。
CSSに対応するHTMLがどのタグだったとしても、同じ見た目を提供できるようにします。


/* × 要素にスタイルを指定する */
h2 { font-size:120%; }
/* ○ クラス名を付与してスタイルを指定する
 →要素が変わってもスタイルシートを変える必要が無い */
.subtitle { font-size:120%; }

/* × 場所を限定してスタイルを指定する */
.header .logo {
background-image:url(/img/logo.png);
width: 250px;
height: 25px;
}
.footer .logo {
background-image:url(/img/logo-small.png);
width: 100px;
height: 15px;
}

/* ○ クラス名を付与してスタイルを指定する
→場所を限定しないので、サイドバーやメインエリアでも使える*/
.logo-large {
background-image:url(/img/logo.png);
width: 250px;
height: 25px;
}
.logo-small {
background-image:url(/img/logo-small.png);
width: 100px;
height:15px;
}

BEM

概要

  • Block、Element、Modifierの略。
  • HTML構造を明確にすることに軸をおいた設計ツール、及びその手法です。厳格な命名規則が特徴です。クラス名が長くなるので、敬遠する人も多いです。
  • ロシアのYandex社によって考案されました。

考え方

要素をBlock、Element、Modifierの3つに分け、命名規則を元にClass名を記述します。

命名規則

「block__element–modifier」のように、BEMでは「__」「_」「-」を単語と単語を区切るために使用していて、これをセパレーターと呼んでいます。
BEMではBlock、Element、Modifierそれぞれの区切りに、一貫したセパレーターを使うことが重要とされます。

1. Block (=かたまり)

ヘッダー・フッター・ナビゲーション・記事・検索エリアなどのパーツのまとまりを指します。
Blockはどこにでも置くことができ、Blockの中にBlockを含めることも可能ですが、CSSではBlockを入れ子にしてスタイルを指定してはいけません。
なぜなら、Blockは完全に独立し、どの場所に移動しても単体で動作可能である必要があるからです。

BlockとElementの区切りは、「Block__Element」のように、アンダースコア2つで接続します。必ずしも2つである必要はありませんが、class名を見るだけでBEMを利用していると分かりやすいので、2つつけることを推奨します。


<div class="wrapper"> /*Block*/<br>   <div class="header"> /*Block*/<br>     <div>logo</div> /*Block*/<br>   </div>   <div class="mainarea"> /*Block*/<br>     <section class="box">~</section> /*Block*/<br>     <section class="box box-white">~</section> /*Block*/<br>     <section class="box"><h2 class="box__title">~</p></section> /*Block+Element*/<br>   </div>   <div class="footer">~</div> /*Block*/<br> </div> </code></pre> <h4>2. Element (=要素)</h4> Blockの中の一つ一つの要素がElementに当たります。<br>記事ならば、タイトル(h2)・記事本文(p)などのパーツであるElementから構成されます。<br> Modifierとの区切りは、「Element&#45;&#45;Modifier」のように、ハイフン2つで接続します。<br> <br> <pre><code class="language-html"><br> <div class="search"> /*Block*/<br>  <a href="#" class="link"></a> /*Element*/<br>  <a href="#" class="link link--disabled"></a> /*Element+Modifier*/<br> </div>

3. Modifier (=修飾子)

同じBlock またはElement を、色、大きさを変えるなど別の種類に分ける(派生させる)際に使います。改めてElementを作るのではなく、Modifier(拡張子)を使って派生させます。
名前(key)と値(value)を持ち、複数のModifierを同時に使用することができます。
Block(又はElement)とModifierとの区切りと、Modifierのkeyとvalueの区切りは、「Block_key_value」または「Element_key_value」のように、区切り文字にアンダースコア1つを使用します。

例:BlockのModifier「Block_key_value」

<ul class="list list_type_disc"> <li class="list__item"></li> <li class="list__item"></li> </ul> <ul class="list list_type_none"> <li class="list__item"></li> <li class="list__item"></li> </ul>
例:ElementのModifier「Element_key_value」

<ul class="tubmenu"> <li class="tubmenu__item"></li> <li class="tubmenu__item tubmenu__item_state_current"></li> <!-- ↑状態がcurrentであるというclass --><br> <li class="tubmenu__item"></li> </ul>

SMACSS

概要

  • Scalable and Modular Architecture for CSS の略。「スマックス」と読みます。
  • OOCSS,BEM の流れを汲んだコーディングルールです。 Jonathan Snook氏によって考案されました。
  • CSSをより体系立て、より構造化させることで制作とメンテナンスをより容易に行うことを目指します。

考え方

おおまかに以下の5つのルールによって構成されます。

  • Base – ベースルール
  • Layout – レイアウトルール
  • Module – モジュールルール
  • State – 状態(ステート)ルール
  • Theme – テーマルール

1.Base – ベースルール

ベースはサイトのデフォルトのスタイル設定で、Reset.cssやNomalize.cssもこちらに含まれます。
サイト全体のフォントサイズや行間、a要素の文字色や:hoverなど、タグに直接設定するものはベースルールとして記述します。

2.Layout – レイアウトルール

ヘッダー・フッター・ナビゲーション・メインコンテンツ・サイドバーなど大枠のレイアウトルールを指定するためのルールです。

命名規則

クラス指定で接頭語(layout-やl-)を付与、又はIDを付与することをSMACSSでは推奨しています。
※IDは場合によってはCSSを複雑にしてしまうので利用する場合は注意が必要ですが、ヘッダーやフッター等汎用的に使われるIDもあるので、SMACSSではID利用を制限していません。


.l-main{
width: 80%;
float: left;
}
.l-fixed .l-main { /* px指定にする場合は、bodyタグ等にl-fixedクラスを付与 */
width: 640px;
}

3.Module – モジュールルール

モジュールは、ボタンやテキスト、タブなどすべての再利用可能なパーツを指します。
クラス名は、モジュール名-サブクラス名の順番で書きます。

命名規則

親モジュールの名前を、接頭語として付与します。
クラス名は、divやspanなどには付与しますが、liやaなどは必ずしも付与する必要はありません。
見出しはh2←→h3などの変更が起こりがちなので、クラス名で区別することをお勧めします。


<div class="l-main"> <div class="box"> <h2 class="box-title">boxタイトル</h2> <p class="box-description">説明</p> </div> </div>

4.State – 状態(ステート)ルール

主にjavascriptで操作されるクラスを指定します。
特定の状態によって.is-disable、.is-active、.is-currentなどを付与して、スタイルを上書きします。例:リンク押下済み、非活性、選択時などのスタイル


<div class="l-main"> <div class="box is-disable"> <h2 class="box-title">boxタイトル</h2> <p class="box-description">説明</p> </div> </div>

.box.is-disable{
display: none; /* is-disabledが付与されたboxは非表示 */
}

5.Theme – テーマルール

テーマは全体のスタイルを変更する場合に使いますが、機会は少ないかも知れません。
メインスタイルの後に読み込ませてスタイルの上書きをしたり、クラスを付加して後からスタイルを変更させたりします。


/* main.css */
a {
color: #00f;
}
.box {
background-color: #fff;
}

/* theme.css:main.cssの後から読み込ませる */
a {
color: #f00;
}
.box {
background-color: #eee;
}

まとめ

今回ご紹介した設計手法以外にも考え方は色々ありますが、有名どころと思われるものをまとめてみました。
比較すると、OOCSSとSMACSSはマルチクラス、BEMはシングルクラスに近いのかなと思いました。
ルールが複雑なものもあるので、最初にきちんと設計することが重要です。
どのような手法を使っても良いと思いますし、これらを元にオリジナルルールを作っても良いです。大切なのは、チームがそれを共通認識できるようにすることです。
ドキュメントを作ったりタスク管理ツールやwikiで共有するのも良いでしょう。
プロジェクト管理ツールについては以下にもまとめているので、興味あればご参照ください。宣伝です。笑

[Qiita][Slack]…プロジェクトを円滑にする便利ツール5選 https://dxo.co.jp/blog/archives/4370
CSSに限らず、手法や考え方はたくさんありますし、どんどん変わっていきます。
私自身も、昔自分が作ったコードを見て、悶絶することも多々あります。
過去の自分を否定することにもなるのですが、恐れずに勉強を重ねていきたいです。
DXO株式会社

DXO株式会社

〒103-0014
東京都中央区日本橋蛎殻町2-13-6
EDGE水天宮8F
E-Mail : contact-info@dxo.co.jp
URL : https://dxo.co.jp