Sass と Stylus の比較 - CSS Preprocessor Advent Calendar 2012

CSS Preprocessor Advent Calendar 2012 19日目の記事です。

CSS Preprocessorは、CSSに拡張機能を持たせるメタ言語と呼ばれるものです。
CSS Preprocessorでよく耳にするものに、SassやLessがあります。
私も以前からSassを使用していましたが、最近Stylusを使い始めたので、SassとStylusの比較を行ってみます。

拡張子とシンタックス

Sass

使用できる拡張子は.sassと.scssの2つ。
拡張子によってSass記法かSCSS(Sassy CSS)記法に分かれます。

Sass記法(.sass)

#header
  color: #000
  h1
    font-size: 2em

SCSS記法(.scss)

#header {
  color: #000;
  h1 {
    font-size: 2em;
  }
}

SCSS記法の方がもともとのCSSの書き方に近く、多くの人がこのSCSS記法を採用しているように感じます。

Stylus

使用できる拡張子は.stylと.stylusの2つ。
Stylusの利点は、{}などを省略してもしなくてもコンパイルされる点です。
拡張子によって書き方が変わることもなく、どの拡張子でも自由に書くことができます。

SCSS記法のような書き方

#header {
  color: #000;
  h1 {
    font-size: 2em;
  }
}

括弧を外しても良い

#header
  color: #000;
  h1
    font-size: 2em;

コロン、セミコロンまで取っても良い

#header
  color #000
  h1
    font-size 2em

Stylusは、Sassのように書き方が厳密に決められていません。
1つのソースでも、柔軟に書き分けることができますが、コーディングルールを決めておかないと、一貫性のないソースになる可能性があります。

Variables(変数)

Sass

名前の先頭に$をつけることで、変数が使えます。
また文字に変数を隣接する場合には、Interpolation #{ }を使用します。

$siteWidth: 360px;

#wrapper {
  width: $siteWidth;
}

#box-#{$siteWidth} {
  width: $siteWidth / 2;
}

Stylus

名前を=でつなげることで変数にすることができます。
また文字に変数を隣接する場合には、Interpolation { }を使用します。

siteWidth = 360px;

#wrapper {
  width: siteWidth;
}

#box-{siteWidth} {
  width: (siteWidth / 2);
}

Stylusの場合は、@をつけることでプロパティを変数のように扱える機能もあります。

p {
  margin: 8px 0;
  padding: @margin; // padding: 8px 0; になる
}

Mixin, Include

Sass

@mixinと@includeで、特定のプロパティなどを保持することができます。
さらにSass記法のみ、ショートコードが使用できます。

Sass記法, SCSS記法 (Sass記法は、中括弧なし)

@mixin border-radius($n: 2px) {
  -webkit-border-radius: $n;
  border-radius: $n;
}

div {
  @include border-radius;  
}
p {
  @include border-radius(4px);
}

Sass記法 (ショートコード)

=border-radius($n: 2px) // @mixinと同じ
  -webkit-border-radius: $n
  border-radius: $n

div
  +border-radius // @includeと同じ

p
  @include border-radius(4px) // ショートコードを使わなくてもいい

Stylus

Stylusの場合は、先頭に何も置かなくてもMixinとIncludeを行うことができます。

border-radius(n = 2px) {
  -webkit-border-radius: n;
  border-radius: n;
}

div {
  border-radius();
}
p {
  border-radius(4px);
}
a {
  border-radius: 4px; // 普通のプロパティに見えますが、コンパイルするとMixinの内容が反映されます
}

またStylusのMixinでは、自動ローカル変数として、argumentsを利用することもできます。

border-radius() {
  -webkit-border-radius: arguments;
  border-radius: arguments;
}

box-sizing() {
  -moz-box-sizing: arguments;
  box-sizing: arguments;
}


a {
  border-radius: 4px;
  box-sizing: border-box;
}

Stylusのコンパイル後

a {
  -webkit-border-radius: 4px;
  border-radius: 4px;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

Mixinを使用することにより、複数プロパティの格納や、既存のプロパティをInclude扱いにすることもできます。
この機能によって、既存のCSSプロパティを、後から拡張することもできます。

制御構文

Sass

if, each, whileなどが用意され、それぞれ利用することができます。

// @if
$legacy: false;
.clearfix {
	@if $legacy {
		zoom: 1;
	}
	&:after {
		content: '';
		clear: both;
		display: block;
	}
}

// @each
div {
  @each $prefix in "-webkit-", "-moz-", "" {
    #{$prefix}border-radius: 4px;
  }
}

// @while
$i: 1;
@while $i < 4 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i + 1;
}

// @for
@for $i from 1 through 100 {
  .item-#{$i} { width: 2em * $i; }
}

Stylus

Stylusの場合は、Sassほど多く制御構文は用意されていません。

// if
legacy = false;
.clearfix {
	if legacy {
		zoom: 1;
	}
	&:after {
		content: '';
		clear: both;
		display: block;
	}
}

// for (Sassの@eachのような使い方)
for prefix in -webkit- -moz- "" {
  {prefix}border-radius: 4px;
}

// for
for i in 1..100 {
  .item-{i} { width: 2em * i; }
}

Sassは、制御構文と@extendなどを一緒に利用することができますが、Stylusにはそれができません。
複雑な構築を行うのあれば、Sassの方が良いかもしれません。

まとめ

Stylusを使い始めてまもないですが、面白いメタ言語だったのでStylusを紹介させて頂きました。
Stylusは、Sassのように高機能ではありません。CSSをフレームワークのように組んでいきたい人には向かないかもしれません。

Stylusの記法は、柔軟性があり、気軽にCSSが書ける、という印象があります。
気になる人はNode.jsをインストールして、Stylusを試してみて下さい。

Sass, Less以外の選択肢として、Stylusも覚えて頂けたら幸いです。