構造的な CSS のための命名規則とルール(CSS Architecture Advent Calendar 2014:前編)

これは CSS Architecture Advent Calendar 201420日目の記事です。
昨日は GeckoTang さんでした。


CSS のメンテナンスがどれだけ難しいか、
変更を加える事がどれだけ大変かという問題にぶつかったのは、
自分で作っている WEB サービスの機能拡張をしている時だった。

CSS 上に、ほとんど同じだが、微妙に値の異なるスタイルが溢れかえり、
日々、増え続けていくスタイルの定義に、歯止めをかけることができなかった。
私は、もうそれをコントロールすることができなくなっていた。


結局、そのときの HTML と CSS は、デザイン更新のタイミングで、すべて捨てることになった。


CSS は難しい。

CSS は、記述を冗長にしないようにするための言語機能、
スタイルの影響範囲をコントロールするための言語機能などが不足している為、
そこに一定のルール、思想がなければ、あっという間にコードはグチャグチャになってしまう。

(それを補うものとして、Sass、LESS などの CSS 拡張言語も登場している。
 Sass、LESS はとても良いものであるのは間違いない。
 しかし依然として、構造的で拡張性のある CSS についても考える必要がある)



この記事では、
どうやれば変更しやすく、破綻しにくい CSS になるのか、
私が心がけている方法について紹介してみる。

これは、既存のいくつかの CSS の方法論(OOCSS, SMACSS, BEM)に、
新しいオレオレルールを、加える事が目的 ではない

構造的な CSS の書き方というのは、
まだまだ広く議論が必要な時期なのではないかなと思う。
クラウドの時代が始まり、昔よりも WEB アプリケーションを開発、運用するハードルが下がった。
それに伴い、HTML、CSSJavaScript 等の重要性は、日々高まり続けているように思う。

私のやり方を見て頂いて、ツッコミをいただければ幸いだし、
見る価値がなければ、そのまま読み流していただければと思う。


はじめに

参考とするコードには、Sass を用いる。


全体ルール

WEB ページに存在する抽象的な考え方として、「テーマ」というものがあると思う。
これは複数のページ間で共有されている、一貫したデザイン上のルールのようなものだ。

図で説明すると、次のようなものだ。

同じテーマであれば、別ページであっても似たようなデザインになる。
ただ、テーマが変わると、デザイン的な依存関係はほとんどない。


全体ルールの1つめ

1つのテーマで読み込む CSS は1つだけとする(※ 複数の CSSファイル を結合したものも含む)
そのテーマを採用している WEB ページは、そのテーマの CSS を必ず読み込まなければいけない。

逆に言えば、
ページごとに、読み込む CSS を加えたり、減らしたりしてはならないというルールだ。

私は、特定のページだけで、例外的に読み込まれる CSS がもたらすレイアウト崩れに散々悩まされた。
結局 CSS にスタイルを記述していて、そのスタイルがどのページ群に影響をあたえるのか、
ハッキリしていないという状況は非常に怖いと思うようになった。


全体ルールの2つめ

1つの WEB ページで、2つ以上のテーマ(CSS)を読み込まない。
テーマとテーマの間に、依存関係はなしだ。

これにより、テーマという概念が、プログラミングでいうところの
ちょっとした「名前空間」の役割を果たすことにもなる。

つまり、テーマ A と テーマ B のそれぞれに、
「active」というような(いかにも名前衝突しそうな)クラス名に対するスタイルを定義したとしても、
それはお互いに、まったく干渉しない。


全体ルールの3つめ

これはルールとは言えないかもしれない。

基本的に、CSS は定義の量が増えてくると、どのようにやっても最終的にツラくなるという認識を持つこと。

なので、CSS の記述量は出来る限り少なく保つ。
出来る限り共通化していくという強い意思のちからが必要だ。

スタイルを書くときは、
「この定義は他の部分でも使いまわせるのでは?」と常に意識しておく。



具体的な規約について

クラス名の命名規則を、次のフォーマットとする。

[prefix]-[*category]-[*name]-[element]

頭に * が付いているものは必須だ。
prefix と、element を省略した場合は、次のようなフォーマットになる。

[*category]-[*name]


覚えるべき命名規則は、これだけだ。



命名規則:「prefix」について

命名規則 [prefix]-[*category]-[*name]-[element] の prefix の部分について、説明する。

今のところ、私が使っている prefix は次の2つだけだ。

  • ui
  • js

ui プレフィックス

私は、スタイルには次の2つの分類があるように思う。

  • (1)そのスタイルだけ、単体で効果がでるもの
  • (2)別のスタイルの中に含まれて、はじめて効果がでるもの

私は(1)をグローバルなスタイル、(2)をローカルなスタイルと呼んで区別している。


具体例を示そう。
グローバルなスタイルと言うのは、次のようなものだ。

<!-- HTML -->
<div class="ui-article">
    <p>昔の人々は、明るい星を結んで星座を思い描きました。
星座を作ったのは、シュメール人という説もありますが、一般的には、約五千年前、
バビロニアの羊飼いたちによって、作られたのが最初と言われています。</p>
</div>


<!-- CSS -->
.ui-article {
  margin: 0;
  padding: 8px 4px;
  background-color: #b6d7a8;
}

見た目はこのようになる ↓



グローバルなスタイルは、その定義単体で、別の場所にも使いまわして良い。

<div class="ui-article">
    <p>昔の人々は、明るい星を結んで星座を思い描きました。
星座を作ったのは、シュメール人という説もありますが、一般的には、約五千年前、
バビロニアの羊飼いたちによって、作られたのが最初と言われています。</p>
</div>

<div class="ui-article">
    <p>初めのころは、十二星座でしたが、その後、四十八星座に増えました。 
 十七世紀に、オランダで望遠鏡が発明され、暗い星も観測できるようになると、
四十八星座のすきまにも新しい星座が作られるようになりました。
そのころ、星を見つけるたびに、こんな会話が交わされたかもしれません。
「新しい星を見つけたぞ。」「だめ。それは、おらンダ。」 
</p>
</div>



一方、ローカルなスタイルとは、次のようなものだ。

<!-- HTML -->
<div class="ui-article">
    <p class="headline">星座の歴史</p><!-- ← ローカルなスタイル:headline は ui-article の中に含まれている -->
    <p>昔の人々は、明るい星を結んで星座を思い描きました。
星座を作ったのは、シュメール人という説もありますが、一般的には、約五千年前、
バビロニアの羊飼いたちによって、作られたのが最初と言われています。</p>
</div>


<!-- CSS -->
.ui-article { ← グローバルなスタイル
  margin: 0;
  padding: 8px 4px;
  background-color: #b6d7a8;

  .headline { ← ローカルなスタイル
    margin: 0;
    padding: 0 4px;
    font-size: 20px;
    background-color: #fff;
  }
}

これはこのように見える。


つまり、ui プレフィックスは、
ここでいうところの「グローバルなスタイル」に対して付与する接頭詞だ。
「ローカルなスタイル」と区別するために用いられる。


js プレフィックス

js プレフィックスは、JavaScript から操作される要素に対して付与される。

jQueryセレクタのための検索キーとしての役割だけを持つ。
js プレフィックスのクラス名に対して、直接スタイルを付与してはならない。

次のようなものは NG だ。

.js-article-body { ← NG: js- に対して、直接スタイルを付与してはいけない
    margin: 0;
    padding: 4px 8px;
}

命名規則:「category」について

命名規則 [prefix]-[*category]-[*name]-[element] の category は、
あまり厳密なルールがあるわけではない。

クラス名に、なんとなく分類らしいものを付与するためのスペースだ。

例えば、あるテーマのトップページに関するスタイルを定義するならば、
次のようなクラス名にしてみるといいかもしれない。

  • ui-toppage-headline
  • ui-toppage-article
  • ui-toppage-article-footer
  • ui-toppage-footer

共通的なスタイルに対しては、次のような category 名もよさそうだ。

  • ui-common-headline
  • ui-common-message-box
  • ui-common-layout

場合によっては、省略してしまっても問題ないと思う。


命名規則:「name」 について

命名規則 [prefix]-[*category]-[*name]-[element] の name は、
利用者が自由に名前付けして良い空間だ。
素敵でわかりやすい名前を、クラスにプレゼントしてあげよう。


命名規則:「element」について

命名規則 [prefix]-[*category]-[*name]-[element] の element は、
ほとんどの場合不要である。

しかし、あるスタイルを定義したときに、そのスタイルがの特定の HTMLエレメント を前提にしたものであれば、
element をくっつけておくようにすると良い習慣になるかも。

例えば、次のような「横並びリスト」を構築したいとする。


/* 横並びリスト(ul 要素に対して使う) */
.ui-horizon-list {
  margin: 0;
  padding: 0;

  li {
    list-style-type: none;
    float: left; // 横並びリスト
  }
}

ui-horizon-list という名前付けでも、もちろん OK だが、
ui-horizon-list-ul という風に、末尾にエレメント名を付与すると、
どのエレメントに対して使うことを想定しているのか、より明確になるのではないかと思う。

/* 横並びリスト */
.ui-horizon-list-ul {
  /* スタイル定義 */
}

最後に

以上が、私が CSS を書くときに気をつけていることの全てである。
見ての通り、あまり厳密なルールを適用しているわけではなく、比較的緩やかな制限となっている。

今のところ、私のプロジェクトではそれなりに統制が取れているような気がしている。



実はこれともう一つ、CSS を書くときに、
CSS の記述量を減らすために、試みていることがある。

それについては、後編として執筆した。

インラインスタイルは、場合によっては使っても良いのではないかという内容だ。
もし興味があれば、是非読んでいただきたい。



この記事を、時間を割いて読んでくださった皆さまの、
何かしらの助けとなれば幸いです。




CSS Architecture Advent Calendar 2014
明日は、naomaru さんの チームで扱う「CSS設計」 です。