dart-sass ではグローバル変数が使えない
dart-sass というか、今後の sass についてです。
下記の記事が新しい@use
記法について詳しく解説されており、大変勉強になりました。
≫Sassを@importから@useに置き換えるための手引き
これまでの sass との違いが解説されていますが、独自フレームワークを作成している自分にとって一番大きな変更点はグローバル変数が使えないという点です。
結論から言うと、@forward
と@use
を併記すれば変数を別ファイルに分割できるという記事です。
今までの書き方
今までは変数、スタイル定義、出力用親ファイルという構成でした。
$color: #000;
.btn{
color: $color;
}
@import "vars";
@import "btn";
@use
記法ではエラーになる
@use "vars";
@use "btn"; // _btn.scss の中では $color は見えない
body{
color: vars.$color; // こちらは問題ない
}
これはエラーになります。
@import
記法では$color
はグローバル変数ですが、@use
記法でのスコープは_vars.scss
にあります。そのため_btn.scss
からはアクセスできません。
common.scss
からはvars.$color
という感じにネームスペースを付与してアクセスします。
対策1:変数とスタイル定義を同じファイルにする
グローバル変数が使えないならば変数とスタイルを同じファイルにまとめてみます。
後から変更できるように!default
を付けておきます。
変数の上書きにはwith
を使います。
// !default を付けると上書き可能になる
$color: #000 !default;
.btn{
color: $color;
}
// with を使うと !default 指定された変数を上書きできる。
@use "btn" with (
$color: #333
);
.btn{
color: #333;
}
この方法なら問題ありませんが、変数が大量にあるモジュールでは見通しが悪くなります。
やはり変数は別のファイルに分けたいです。
@forward
を使う
@forward
は@use
と同じく、ファイルの読み込みです。
違いをざっくり言うと**@forward
はさらに他のファイルから読まれることを前提とした時に使う**という点です。
例えば下記はエラーになります。
//変数定義ファイル
$color: #000 !default; // !default で変更可能にする
// 変数ファイルをまとめて読む
@use "var1";
@use "var2";
@use "var3";
@use "import";
body{
color: import.$color;
}
_import.scss
で@forward
を使えば問題ありません。
// @forward を使って変数ファイルをまとめて読む
@forward "var1";
@forward "var2";
@forward "var3";
@use "import" with {
$color: #ccc;
};
body{
color: import.$color;
}
body{
color: #ccc;
}
@forward
の読み込み元ファイルからはアクセスできない
@forward
にはもうひとつ特徴があります。それは読み込み元からはアクセスできないという点です。
例えば下記はエラーになります。
$color: #000 !default;
@forward "vars";
.btn{
color: vars.$color;
}
@forward
はスコープを転送しているので_btn.scss
からはアクセスできません。
対策2:@forward
と@use
を併記する
というわけで結論です。
@forward
@use
を併記することによって変数ファイルを外に出すことができ、さらに親から上書きすることもできます。
$color: #000 !default;
@forward "vars";
@use "vars"; // 同じファイルを @use でも読む
.btn{
color: vars.$color;
}
@use "btn" with (
$color: #ccc
);
body{
color: btn.$color;
}
.btn{
color: #ccc;
}
body{
color: #ccc;
}
これがベストプラクティスとは言えないでしょうが、誰かがもっと良い方法を考えてくれるまではこの方法を使いたいと思います。
@forward
と@use
を同時に使っていいの?
@forward
と@use
を同時に使っていいの? という点に関しては公式に書かれてました。
If you do write both a @forward and a @use for the same module in the same file, it’s always a good idea to write the @forward first. That way, if your users want to configure the forwarded module, that configuration will be applied to the @forward before your @use loads it without any configuration.
google翻訳さんによると
同じファイルに同じモジュールの@forwardと@useの両方を書き込む場合は、常に@forwardを最初に書き込むことをお勧めします。 そうすれば、ユーザーが転送されたモジュールを構成したい場合、@ useが構成なしでモジュールをロードする前に、その構成が@forwardに適用されます。
ということで問題ないようです。
グローバル変数が使いたければ css変数を使う
もっと気楽にグローバル変数が使いたいという時は css変数を使うほうがいいです。
例えばボタン class のバリエーションを作りたいというなら--btn-color: #333;
みたいなのを定義して、それを上書きするほうがスマートでしょう。