Rhyztech blog

Sassの@use, @forwardについて

tech

Sass はこれまでの@importを将来的に廃止し、新たに@use@forwardのモジュールシステムを使うように動こうとしています。 現在(2020/01)では Dart 版の Sass のみ実装されていますが、LibSass にも実装される予定です。 @use@forwardを簡単に紹介したいと思います。

@use とは?

@use@importと同様に別のファイルの情報を読み取ります。 スタイルの定義は今まで通り、@useを使ったファイルに結合されることになります。 ただし、変数や関数、mixin はファイル単位で名前空間を持ちます。

例えば、次のファイルのようにヘッダー要素を別のファイルに定義し、style.scss で mixin を呼び出す場合、デフォルトでファイル名と同じ名前空間を持つことになります。 そのため、変数や mixin を呼び出す際は<namespace>.<variable><namespace>.<function><namespace>.<mixin> という形式で呼び出すこと必要があります。

// heading.scss
$color: red !default;

@mixin wrapper {
  font-size: 36px;
  color: $color;
}

// 普通のスタイルを定義
h1 {
  color: blue;
}
// style.scss
@use 'heading';

h2 {
  // mixinは名前空間が必要なので、<namespace>.<mixin>で指定する
  @include heading.wrapper;
}
/* 出力されるCSS */

/* 普通のスタイルの定義はそのまま出力される */
h1 {
  color: blue;
}

h2 {
  font-size: 36px;
  color: red;
}

変数や mixin にファイル固有の名前空間が作られるため、グローバルで変数名や mixin 名の重複を心配する必要はなくなります。 そのため、役割ごとにファイルを分けることによって、シンプルな変数名や mixin 名を使うことができるようになります。 @useで呼び出される際の名前空間の名前はデフォルトではファイル名ですが、指定することも可能です。

@use 'src/heading'; // これは heading.hgoehoge の名前空間が生成される
@use 'button' as b; // これは b.hgoehoge の名前空間が生成される
@use 'corners' as *; // 名前空間が生成されず、hogehoge で使える(非推奨

@useを使用した際に変数の値を書き換えることもできます。

// heading.scss
$color: red !default;
$height: 30px !default;
// withを使って変数を書き換えることができます。リストなのでカンマ区切りになります。
@use 'heading' with (
  $color: blue,
  $height: 50px
);

@forward とは?

@useを使うことで名前空間を生成し、ロードしたファイルにスコープが生成され、そのファイルでのみ使用することができます。 しかし、そうなると CSS フレームワークなどで変数や関数が見えなくなる状況が生まれます。

// heading.scss
$color: red !default;

@mixin wrapper {
  font-size: 36px;
  color: $color;
}
// bootstrap.scss
@use 'heading';
// style.css
@use 'bootstrap';

h1 {
  // Error!!
  // bootstrap.scssないで@useでロードしているため、他のファイルからは見えないためエラーになる
  @include bootstrap.wrapper;
}

そのファイルをロードしたファイルにも変数や関数が見えるようにするためには @forwardを使う必要があります。

// heading.scss
$color: red !default;

@mixin wrapper {
  font-size: 36px;
  color: $color;
}
// bootstrap.scss
@forward 'heading';
// style.css
@use 'bootstrap';

h1 {
  // Success!!
  // bootstrap.scssないで@forwardでロードしているため見える
  @include bootstrap.wrapper;
}

@forwardする際にプレフィックスをつけることもできます。

// heading.scss
$color: red !default;

@mixin wrapper {
  font-size: 36px;
  color: $color;
}
// bootstrap.scss
@forward 'heading' as heading-*;
// style.css
@use 'bootstrap';

h1 {
  // "heading-"のプレフィックスが必要
  @include bootstrap.heading-wrapper;
}

Copyright 2021, rhyztech. All Rights Reserved.