@Toro_Unit さんが先日下記のような記事を書いていました。
Stylus の公式サイトを軽く流し見したところ、Sass で気になっていたところが結構解決できそうな感じだったので Basis を Sass から Stylus に書き直してみました。
Sass から Stylus に書きなおすときのポイント
構文
Stylus は : や {}、, を省略してインデントベースで CSS を書くことができます。僕は Sass は Scss 構文しか知らないのですが、Sass 本来の構文だと似たような感じで書けるのですかね?ちなみに僕は混乱しそうだったので省略せずに書きました。
body font-family sans-serif; font-weight normal;
変数
Sass は変数の宣言が CSS のプロパティの記述に似ていて:で定義しますが、Stylus の場合はプログラミング言語チックに = で代入します。
// Sass $gutter: 20px; // Stylus gutter = 20px;
また、Sass では !default というフラグがあり、これをつけて変数宣言しておけば、ライブラリの読み込み側でライブラリを読み込む前に同名の変数を定義することでそれが利用される、みたいなことができました。Stylus でも同様の機能がありますが、こちらもプログラミング言語チックにシンプルに書けます。
// Sass $gutter: 20px !default; // Stylus gutter ?= 20px;
ミックスイン
Sass では必要だった @mixin や @include の表記が不要です。 最初に書いたインデントベースの構文と組み合わせることで、普通の CSS と同じようにミックスインを利用することが可能になります(透過的ミックスイン)。
// Sass
@mixin font($size: 14px) {
font-family: sans-serif;
font-weight: normal;
font-size: $size;
}
body {
@include font(16px);
}
// Stylus
font(size = 14px) {
font-family: sans-serif;
font-weight: normal;
font-size: size;
}
body {
font(16px);
}
body
font 16px;
囲み型のミックスインもシンプルに書けます。
// Sass
@mixin hover() {
&:hover, &:active {
@content;
}
}
@include hover() {
text-decoration: underline;
}
// Stylus
hover() {
&:hover, &:active {
{block}
}
}
+hover() {
text-decoration: underline;
}
extend
Toro_Unit さんの記事にもありましたが、Stylus の extend は子要素まで引き継ぐようになっています。extend を使いたいときはその一部分だけではなくそのコンポーネントごと継承したい場合が多いのでこちらのほうが直感的で便利だなと思いました。
// Sass
.media {
display: flex;
&__figure { ... }
&__body { ... }
}
.profile {
@extend .media;
}
↓↓コンパイル結果
.profile {
display: flex;
}
// Stylus
.media {
display: flex;
&__figure { ... }
&__body { ... }
}
.profile {
@extend .media;
}
↓↓コンパイル結果
.profile {
display: flex;
&__figure { ... }
&__body { ... }
}
また、Stylus の extend もプレースホルダーの利用が可能で、Sass の場合は % でしたが Stylus は $ で定義します。
あと他にも Sass だと呼び出しより後に定義しても継承できたのが Stylus ではできないとか、セレクタの中で定義した場合の扱いが違うとか細かい違いがありました。詳しく検証していないのではっきりはわかりませんが extend 使いまくりたい方は注意が必要かもしれません。
変数の展開
これがいまいち理解できていないのですが、Sass の場合は変数を展開したい場合にとにかく {} で囲っておけばよかったのですが Stylus の場合はそれではエラーとなりコンパイルできない場合がありました。{} がダメだった場合は囲まずに + で連結させるとうまくいったりしました。ドキュメントにもあまり詳しく説明は無いようだったのでコケたら書き換えてみるという感じでやりました(めんどくさい)。
@import
Sass はいちいち一個ずつ @import を書く必要がありましたが、Stylus では * を使って一気にインポートできます。
// Sass @import component/btn @import component/alert @import component/nav // Stylus @import component/*
関数
Stylus は Sass より短く書くことができます。また、明示的に return しなくても勝手に return されるみたいです。僕はよくわからなくなりそうだったので全て明示的に return しました…。
// Sass
@function add($a, $b) {
@return $a + $b;
}
// Stylus
add(a, b) {
a + b;
}
if 文
Stylus はいちいち @ をつけずに if 文を書くことができます。
// Sass
@if (true == foo) {
font-size: 12px;
}
// Stylus
if (true == foo) {
font-size: 12px;
}
あと、これが超うれしいポイントだったのですが、Stylus は if 文の中で @import ができます。Sass の場合は if statetment の中になんちゃらみたいなエラーが出てダメだったんですよね。。Basis は各コンポーネントの class を css に出力するか、それとも変数やミックスインなどのライブラリだけを利用するのか変数で切り替えることができるようになっているのですが、Sass は if 文の中に @import が書けないがために各コンポーネントのファイル全てに if if 書かないといけなくてスマートじゃなかったんですよね。
// Sass - 本当はこうしたいけどコケる
@import core/*
@if (false == is-use-only-core) {
@import component/btn;
@import component/alert;
...
}
// なのでこうしていた(遠い目)
// component/ 以下の全部のファイル
@if (false == is-use-only-core) {
.c-btn { ... }
}
while 文
Sass には while 文がありますが、Stylus にはありません。Basis はグリッドシステムの class を生成するのに再帰処理で最大公約数を求めて云々する部分がありそこで while を使っていたので関数を再帰呼び出しする形に書き直しました。
//Sass
@function bs-gcd($a, $b) {
$r: $a % $b;
@while $r != 0 {
$a: $b;
$b: $r;
$r: $a % $b;
}
@return $b;
}
// Stylus
bs-gcd(a, b) {
if (b == 0) {
return a;
}
return bs-gcd(b, a % b);
}
色を明るく・暗くする関数
すごくニッチかもですが…。Sass にも Stylus にもカラーコードを明るくしたり暗くしたりする組み込み関数があります。Sass の場合はこれらの関数の動作が直感的で、「この色を○%明るくする」という感じなのですが、Stylus のほうは一工夫必要でした。これも詳しく検証はしていないのですが、Stylus の場合は恐らく「この色の明るさを○%にする」という感じなのかなと思いました。
// Sass lighten($hex, 20%); // Stylus lightness(hex, (lightness(hex) + 20%));
まとめ
ということでとりあえず Basis 本体は Stylus 化できたので、テンプレートとかアドオンも Stylus 化していきたいと思います。難しいことをしなければ Sass とそんなに違いは無いですし、単純に記述量が減るのでなかなか良いなと思います。


