部屋とYシャツと私

Good-bye Compass, Good-bye Ruby.

部屋とYシャツと私、AutoprefixerとSpritesmithとLibsassの話。

愛しのMapleは、フレームワークというかGrunt詰め合わせセットなのですが、Grunt自体はNode.js依存で、使っているCSSプリプロセッサはSassでRuby依存なので、なんだかキメラみたいで気持ち悪い。いっそのこと、プリプロセッサはStylusにしてNode.jsで統一しようか、むしろMiddlemanみたいにRubyで統一するか、考えものだ。とりあえずはCompassを辞めてみようという結論に至ったので代替案を探る。

MapleでCompassを使っている理由は2つ。

  • ベンダープレフィックスを付ける手間をなくしたい
  • CSSスプライトを自動化したい

これらをGruntプラグインでなんとか置き換えれないものか。

grunt-autoprefixer

ちょうど、myakura氏のブログで取り上げられていたAutoprefixerが便利そうなので、これのGruntプラグインがないか探したらもちろんあった。

autoprefixer: {
  options: {
    browsers: ['ios >= 5', 'android >= 2.3']
  },
  dist: {
    src: '../files/css/maple.css'
  },
}

Gruntの設定も至極簡単だ。対象のCSSファイルとと対応するバージョンを指定するだけだ。 あとは正規のプロパティ書いておくだけ、Autoprefixerがバージョンに応じてベンダープレフィックス付きのプロパティを追加・削除してくれる。

Compassのミックスインによる書き方よりも、真っ当というか、なんかこっちの実装のほうが素敵だと素直に思った。あと対応するバージョンの指定方法も、CompassみたいにベンダーごとにON/OFFするんじゃなくて、last 2 versionsといった書き方もできたり、蟹ウゼのデータを元にしてあったりと柔軟に指定できるのも魅力かな。

grunt-spritesmith

CSSスプライトを自動化するためにCompassを使用しはじめたのもあって、移行しんどかった。使い勝手的にはCompass Spriteのほうが今のところは良いと思う。

しかし、Spritesmithに変更することでCSSプリプロセッサに依存せずにCSSスプライトの自動化を手に入れることができる。MapleではSass用にコードを吐き出してるけど、Stylus用にも吐き出せるし、生のCSSでもできる。

$_bird1: 0px 149px 0px -149px 60px 49px 302px 198px "/files/img/sprite/tabs.1383826639213.png";
$_bird2: 0px 0px 0px 0px 180px 147px 302px 198px "/files/img/sprite/tabs.1383826639213.png";
$_bird3: 182px 0px -182px 0px 120px 98px 302px 198px "/files/img/sprite/tabs.1383826639213.png";
$_bird4: 62px 149px -62px -149px 60px 49px 302px 198px "/files/img/sprite/tabs.1383826639213.png";

// $list: <X> <Y> <Offset X> <Offset Y> <Width> <Height> <Total Width> <Total Height> <Image Path>

@mixin sprite($isParent, $sprite) {
  @if $isParent == "parent" {
    $imagePath: nth($sprite, 9);
    background-image: url("#{$imagePath}");
    background-repeat: no-repeat;
    background-size: round( nth($sprite, 7) / 2 ) round( nth($sprite, 8) / 2 );
  } @else {
    width: round( nth($sprite, 5) / 2 );
    height: round( nth($sprite, 6) / 2 );
    background-position: round( nth($sprite, 3) / 2 ) round( nth($sprite, 4) / 2 );
  }
}

Spritesmithはタスクを実行すると、任意の画像をスプライト画像にまとめて、上記のようなコードを吐き出してくれる。要は、$_bird1のようなスプライト画像のWidth/Heightやオフセット値をまとめたリスト型の変数を提供してくれるので、あとはそのデータを使って自分で独自のミックスイン(Retina対応している)を作成すればよい。このデータさえあればCompassの関数を使わなくて良くなる。

sprite: {
  dist: {
    dt: '<%= Date.now() %>',
    src: '../files/img/sprite/tabs/*.png',
    destImg: '../files/img/sprite/tabs.<%= sprite.dist.dt %>.png',
    imgPath: '/files/img/sprite/tabs.<%= sprite.dist.dt %>.png',
    destCSS: '../files/css/sass/libs/_sprite.scss',
    algorithm: 'binary-tree',
    padding: 2,
    cssTemplate: 'spritesmith.mustache'
  }
}

各画像のオフセット値が分かるのでbinary-treeという、単純に縦並べ、横並べじゃなくてCompassのSmartみたいな、詰め込んだ並べ方ができるのも良さげ。

Gruntでの設定がややめんどいし、キャッシュバスターのためにDate.now()の値をファイル名に入れてるけど、タスクが実行される度に画像に変更がなくても新たにスプライト画像を生成してしまうし、以前のスプライト画像もCompassみたいに勝手に削除されない。この辺もうちょっと頑張ってみる必要性がある。

Libsass

ということで、Compassの呪縛からはとりあえず解放されたのでSassもC実装のLibsassにしてみた。LibsassはRubyで書かれていたSassのコンパイラをCで書きなおしたもの。それをNode.jsから利用できるようにしたのがnode-sassで、それのGruntプラグインがgrunt-sass。ややこいけど要はSassだけどRubyがいらないシロモノ。

しかもCで書かれているので、爆速でコンパイルされるらしいよ(まだ大きいファイルで試してないけど)とりあえず今んとこ絶賛開発中でSCSSファイルしかコンパイルできてないし、RubySassでうまくコンパイルされるけど、Libsassではコンパイルできないってバグもあるし、ご利用は慎重にって感じ。個人的にはそんなにSassっぽいというかCSSプリプロセッサ全開!な書き方してないし、変数使えたらいいなぁ程度なので、そこまで困らないはず。。。

というわけで、Sass使いながらでも、

Good-bye Compass, Good-bye Ruby.

できました。おしまい(・ω<)