Sassの存在意義への補足

Sass存在意義の話があんまりうまく伝わってない感じなので、3の別々に書けてSassで関連付けられるということについて少しだけ書く。抽象的な概念の話なので具体的な説明というのもなかなか難しいけど、CSSフレームワークを使う時にどうなるかみたいなことを取り上げる。

Twitter Bootstrapを始めCSSフレームワークはいくつもあるが、それらはだいたいユニークなクラス名を持っている。例えばTwitter Bootstrapで2カラムレイアウトを作る場合は以下のようなHTMLにしなくてはならない

<div class="row">
  <div class="span4">...</div>
  <div class="span8">...</div>
</div>

div要素はsectionaside要素などを使っても良いが、クラス名はこうでなくてはならない。Sass(やLESS)があるとまず変わるのはここ。

<div class="wrapper">
  <aside>...</aside>
  <div role="main">...</div>
</div>

ほとんどのケースでこのようにHTML文書側では適切な要素の使用やクラス名の割り振りだけで良くなる。このことが意味するのはHTML文書のソースが(自己満足的に)キレイになるとかそういう話でもあるんだけど、もっと重要なのはコンテンツを把握できるバックエンド側で適切にマークアップすることができるようになるという点だと思う。クラス名の命名規則等のコーディング規約で少しは改善できるが、根本的な解決にはならない。

.wrapper {
  @extend .row;

  > aside {
    @extend .span4;
  }
}

[role="main"] {
  @extend .span8;
}

CSSのHTML文書への適用はSassでCSSで定義したデザインを継承する形で行う。CSSフレームワークやOOCSSではHTMLで複数のクラスを割り当てる形なわけだけど、SassやLESSでそれを代行できると言い換えても良い。

CSSに慣れた人ならわかると思うけど、これはCSSのセレクターの工夫でどうにかなる部分ではある。でもそれではCSSフレームワークのような汎用的なシステムは作れないし、HTMLの構造にセレクターが強く依存するのでテストすら汎用的に書けない。あらゆる点でワンオフなCSSになってしまう。

対して、SassやLESSでデザインを継承する形で書く場合、特にHTMLの構造を考慮することなくデザインを行う(CSSを書く)ことができる。とりあえず直感的なクラス名のセレクターで好きに書けば良い。具体的に言うのならならサイトロゴやclearfixなどデザインや機能単位でそれぞれ定義してやるだけ。

.add-quote-mark {
  padding-left: 48px;
  min-height: 48px;
  background: {
    image: url("/img/quote.png");
    repeat: no-repeat;
    size: 48px 48px;
  }
}

例えばblockquote要素で使うために引用符の画像を背景に仕込むというようなデザインを定義するなら、こういう形でそのためのプロパティーだけを書けば良い。マージンやフォントの変更などもそれぞれ別に定義する。

.default-margin {
  margin: 2em 0 0 0;
}

.quote-text {
  font: {
    family: "Palatino", "Palatino Linotype", serif;
    style: italic;
  }
}

テストは個々のデザインごとにテストすれば良いので、blockquote要素で使われるデザインだからといってテストでもblockquote要素を使う必要はない。

<div class="add-quote-mark">Lorem ipsum dolor sit amet.</div>
<div class="default-margin">Lorem ipsum dolor sit amet.</div>
<span class="quote-text">Lorem ipsum dolor sit amet.</span>

実際にはそれぞれをsection要素で括って見出しをつけたり、テストページといえども見やすいように構造と体裁を整えた方が良いけど、基本はこんなもので良い。長い行の折り返しを省略するtext-overflow: ellipsisを使うならサンプル文字列を長文にするとか、デザインに合わせてテストをちゃんと書くだけ。ここでも最終的にこのデザインが利用されるHTML文書のことを考える必要はほとんどない。

LESSではこの定義したデザインをCSSにコンパイルすることなくほぼ直接テストできるので(less.js使うだけ)、その点で大きくSassに優る。Sassではテスト用のCSSを別途コンパイルする必要があるので、そこをどうにかするための環境を整えるのはかなり面倒くさい。僕はSassをCSSにコンパイルして返すCGIを作ってそれを利用してやってるけど色々アレで、もっとなんかこうless.js並に手軽な仕組みが欲しいところ。

[role="main"] blockquote {
  @extend .default-margin;
  @extend .add-quote-mark;
  @extend .quote-text;
}

最後にSassでこのデザインを継承する。理想的に書くことが出来ればワンオフになるのはこの@extendを使うファイル(とコンパイルされたCSS)だけ。

<div role="main">
  <blockquote class="add-quote-mark default-margin quote-text">...</blockquote>
</div>

CSSフレームワークやOOCSS的なアプローチだとHTMLでこうする必要がある。CSSをよく知らないバックエンド開発者に「add-quote-markdefault-marginquote-textrole="main"配下のblockquote要素のクラスに追加してください」とか「デザイン変えるためにテンプレートを更新したけどGitわからないので取り込んでください」とかお願いしているところを想像して欲しい。


@extendによるデザインの継承はセレクターの数の上限というとんでもないバギーなInternet Explor 9以下の仕様にぶつかりやすいとか色々SassやLESSの暗黒面については端折って書いててずるいとか、Sass 3.2では@extendで使えるplaceholderセレクターというものが追加されてこのあたりの話が少し変わるとか、他にも色々あるのでちゃんとまとめたい気はする。@extendをちゃんと使って書く方法は僕もまだまだ手探りしてたりするのでちゃんと書ける気しないけど。