14
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CSSAdvent Calendar 2020

Day 11

新しいSassの@use、@forwardを組み合わせて変数を別ファイルに分割する

Last updated at Posted at 2020-12-19

dart-sass ではグローバル変数が使えない

dart-sass というか、今後の sass についてです。
下記の記事が新しい@use記法について詳しく解説されており、大変勉強になりました。

≫Sassを@importから@useに置き換えるための手引き

これまでの sass との違いが解説されていますが、独自フレームワークを作成している自分にとって一番大きな変更点はグローバル変数が使えないという点です。

結論から言うと、@forward@useを併記すれば変数を別ファイルに分割できるという記事です。

今までの書き方

今までは変数、スタイル定義、出力用親ファイルという構成でした。

_vars.scss
$color: #000;
_btn.scss
.btn{
  color: $color;
}
common.scss
@import "vars";
@import "btn";

@use記法ではエラーになる

common.scss
@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を使います。

_btn.scss
// !default を付けると上書き可能になる
$color: #000 !default;

.btn{
  color: $color;
}
common.scss
// with を使うと !default 指定された変数を上書きできる。
@use "btn" with (
  $color: #333
  );
出力結果
.btn{
  color: #333;
}

この方法なら問題ありませんが、変数が大量にあるモジュールでは見通しが悪くなります。
やはり変数は別のファイルに分けたいです。

@forwardを使う

@forward@useと同じく、ファイルの読み込みです。
違いをざっくり言うと**@forwardはさらに他のファイルから読まれることを前提とした時に使う**という点です。

例えば下記はエラーになります。

_var1.scss
//変数定義ファイル
$color: #000 !default; // !default で変更可能にする
_import.scss
// 変数ファイルをまとめて読む
@use "var1";
@use "var2";
@use "var3";
common.scss
@use "import";

body{
  color: import.$color;
}

_import.scss@forwardを使えば問題ありません。

_import.scss
// @forward を使って変数ファイルをまとめて読む
@forward "var1";
@forward "var2";
@forward "var3";
common.scss
@use "import" with {
  $color: #ccc;
};

body{
  color: import.$color;
}
出力結果
body{
  color: #ccc;
}

@forwardの読み込み元ファイルからはアクセスできない

@forwardにはもうひとつ特徴があります。それは読み込み元からはアクセスできないという点です。

例えば下記はエラーになります。

_vars.scss
$color: #000 !default;
_btn.scss
@forward "vars";

.btn{
  color: vars.$color;
}

@forwardはスコープを転送しているので_btn.scssからはアクセスできません。

対策2:@forward@useを併記する

というわけで結論です。

@forward @use を併記することによって変数ファイルを外に出すことができ、さらに親から上書きすることもできます。

_vars.scss
$color: #000 !default;
_btn.scss
@forward "vars";
@use "vars";  // 同じファイルを @use でも読む

.btn{
  color: vars.$color;
}
common.scss
@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;みたいなのを定義して、それを上書きするほうがスマートでしょう。

14
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?