🔰

Sassの@useってなに?

2023/12/18に公開

こんにちは!ラブグラフ開発インターンのけいすけです。
Sassの@useを知らなかったので調べてみました。

@useとは

メンバー(変数、関数、ミックスイン)を他のSassファイルから読み込むための命令です。@useを使って読み込まれたファイルはモジュールと呼ばれます。

  • foundation/_code.scss
  • foundation/_lists.scss

というモジュールがあるとします。

foundation/_code.scss
code {
  padding: .25em;
  line-height: 0;
}
foundation/_lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}

これらのファイルを読み込むには、次のように書きます。
ただし、アンダースコア、拡張子は必要ありません。

style.scss
@use 'foundation/code';
@use 'foundation/lists';

次のコマンドを実行すると、

sass style.scss style.css

コンパイル後のCSSは次のようになります。

style.css
code {
  padding: .25em;
  line-height: 0;
}

ul, ol {
  text-align: left;
}
ul ul, ol ol {
  padding-bottom: 0;
  padding-left: 0;
}

モジュールのメンバーにアクセスする

モジュールで定義されたメンバーにはそれぞれ次の書き方でアクセスできます。

  • 変数:<namespace>.<variable>
  • 関数:<namespace>.<function>()
  • ミックスイン:@include <namespace>.<mixin>()

<namespace>はデフォルトではURLの最後の部分になります。
ただし、アンダースコア、拡張子は必要ありません。

src/_corners.scss
$radius: 3px;

@mixin rounded {
  border-radius: $radius;
}
style.scss
@use "src/corners";

.button {
  @include corners.rounded;
  padding: 5px + corners.$radius;
}

コンパイル後のCSS

.button {
  border-radius: 3px;
  padding: 8px;
}

namespaceを変える

<namespace>はデフォルトではURLの最後の部分ですが、@use "<url>" as <namespace>と書くことで、namespaceを変えることができます。

src/_corners.scss
$radius: 3px;

@mixin rounded {
  border-radius: $radius;
}
style.scss
@use "src/corners" as c;

.button {
  @include c.rounded;
  padding: 5px + c.$radius;
}

コンパイル後のCSS

.button {
  border-radius: 3px;
  padding: 8px;
}

メンバーをプライベートにする

-または_で始めるメンバーは、そのメンバーが定義されたモジュールでしかアクセスできなくなります。

src/_corners.scss
$-radius: 3px;

@mixin rounded {
  border-radius: $-radius;
}
style.scss
@use "src/corners";

.button {
  @include corners.rounded;

  // エラー:$-radius は`_corners.scss`の外では使えない
  padding: 5px + corners.$-radius;
}

!default

変数の定義の後ろに!defaultと書くことで変数のデフォルト値を設定できます。変数にまだ値が割り当てられていない時のみ指定した値を割り当てます。変数に既に値が割り当てられている場合は、指定された値が代入されることはありません。@use <url> with (<variable>: <value>, <variable>: <value>)と書くことでデフォルト値を上書きできます。

例1

_library.scss
$red: #f00 !default;
$border: 1px solid $red;
$text-shadow: 2px 2px $red;

code {
  border: $border;
  text-shadow: $text-shadow;
}

style.scss$redのデフォルト値の#f00#800で上書きしています。

style.scss
@use 'library' with (
  $red: #800,
);

コンパイル後のCSS

code {
  border: 1px solid #800;
  text-shadow: 2px 2px #800;
}

例2

例1だけだと変数の再代入との違いが分かりづらいと思ったので、もう一つ例をみてみましょう。
_library.scssの内容は例1と同じです。

_library.scss
$red: #f00 !default;
$border: 1px solid $red;
$text-shadow: 2px 2px $red;

code {
  border: $border;
  text-shadow: $text-shadow;
}

style.scsswith ($red: #800);を省いて、library.$red: #800と書いてみました。
この場合、style.scssの中では$redの値は#800になりますが、_library.scssの中では$redの値はデフォルト値の#f00が使われます。

style.scss
@use 'library';

library.$red: #800;

コンパイル後のCSS

code {
  border: 1px solid #f00;
  text-shadow: 2px 2px #f00;
}

変数への再代入

変数を定義した後で値を再代入できます。

_library.scss
$color: red;
_override.scss
@use 'library';
library.$color: blue;
style.scss
@use 'library';
@use 'override';
@debug library.$color; //=> blue

パーシャル

_code.scssのように_で始まるファイルはパーシャルと呼ばれます。パーシャルはモジュールとしてのみ使われ、コンパイルされません。

Indexファイル

@useでフォルダ名を指定した場合は、そのフォルダ内の_index.scssまたは_index.sassが読み込まれます。

foundation/_code.scss
code {
  padding: .25em;
  line-height: 0;
}
foundation/_lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}
foundation/_index.scss
@use 'code';
@use 'lists';
style.scss
@use 'foundation';

コンパイル後のCSS

code {
  padding: .25em;
  line-height: 0;
}

ul, ol {
  text-align: left;
}
ul ul, ol ol {
  padding-bottom: 0;
  padding-left: 0;
}

@importの問題点

Sassには@importという@useと同様の命令が既にありますが、@use@importが持つ問題を解決するために導入されました。@importは数年後にSassから削除される予定で、今後は@useを使うことが推奨されています。

@importの問題点とは次のようなものです。

  • @importは全てのメンバーをグローバルにしてしまう。これによってそれぞれのメンバーがどこで定義されたものなのか分かりづらくなってしまいます。
  • 全てのメンバーがグローバルなため、ライブラリは名前の衝突を避けるためにプレフィックスをつけないといけない。
  • @importで読み込まれたスタイルシートは読み込まれるたびに実行されるため、コンパイルに余計に時間がかかってしまう。
  • プライベートなメンバーを定義する方法がない。

@importとの違い

  • @useは現在のファイルでのみメンバーをアクセスできるようにする。グローバルスコープでアクセスできるようにはならない。
  • namespaceによって各メンバーがどのモジュールで定義されているのかが分かりやすくなった。他のモジュールで定義されているメンバーと名前の衝突が起こる心配なく、短い名前を使えるようになった。
  • @useはモジュールを一度だけ読み込む。間違って同じモジュールを複数回読み込む心配がない。
  • @useはファイルの先頭に書かないといけない。ネストはできない。
  • 1つの@useは1つのURLしか指定できない。

最後に

読んでいただきありがとうございました!@use使っていきましょう!

参考

https://sass-lang.com/documentation/at-rules/use/

https://sass-lang.com/documentation/at-rules/import/

ラブグラフのエンジニアブログ

Discussion