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;みたいなのを定義して、それを上書きするほうがスマートでしょう。