SCSS を書き進めていくと、1つの style.scss が数百行、数千行とふくらんでいきます。目的のスタイルを探すのに時間がかかり、どこに何を書けばいいのかも曖昧になってきます。
Sass には、ファイルを役割ごとに分割して管理するための仕組みが用意されています。それがパーシャルと @use です。変数はここ、ボタンのスタイルはここ、と置き場所を決めておけば、ファイル名を見るだけで目的のコードにたどり着けます。
この記事では、パーシャルの作り方と @use での読み込み、フォルダ単位でまとめる _index.scss と @forward、そして実際によく使われるディレクトリ構成までを解説します。
目次
パーシャルはアンダースコアで始まるファイル
ファイル名の先頭にアンダースコア(_)を付けた SCSS ファイルをパーシャルと呼びます。_variables.scss や _button.scss のような名前です。
パーシャルの特徴は、単体では CSS ファイルに変換されないことです。あくまで他のファイルから読み込まれる部品として扱われます。アンダースコアの付いていない style.scss だけが style.css として出力されます。
src/
├── style.scss ← これだけが style.css になる
├── _variables.scss ← パーシャル(単体では出力されない)
└── _button.scss ← パーシャル
アンダースコアを付け忘れると、variables.css のような中身のほとんどないファイルまで書き出されてしまいます。読み込まれる側のファイルには必ずアンダースコアを付ける、と覚えてください。
@use で読み込む
パーシャルを読み込むには @use を使います。書くときは、先頭のアンダースコアと拡張子を省略します。_variables.scss を読み込むなら @use "variables"; です。
$color-primary: #007bff;
$color-text: #333;
$space-md: 16px;
// 変数を使うファイルでも、そのファイル自身が @use する必要がある
@use "variables";
.button {
padding: variables.$space-md;
background-color: variables.$color-primary;
color: #fff;
}
読み込んだファイルの変数や mixin には、ファイル名の名前空間を付けてアクセスします。variables.$color-primary という書き方がそれです。少し長く感じますが、「この値はどのファイルで定義されたものか」が一目で分かるという利点があります。
名前空間を短くする・省く
名前空間は as で好きな名前に変えられます。as * と書けば名前空間なしで使えますが、どのファイル由来の変数なのか分からなくなり、名前の衝突も起きやすくなります。多用は避けましょう。
// 名前空間を v に短縮する
@use "variables" as v;
.button {
color: v.$color-primary;
}
// 名前空間なしで使う(衝突に注意)
@use "variables" as *;
.button-secondary {
color: $color-text;
}
なお @use はファイルの先頭に書く決まりです。スタイルルールより後ろに書くとエラーになります(@charset と、モジュールの設定に使う変数の宣言だけは前に置けます)。
_index.scss でフォルダ単位にまとめる
ファイルが増えてくると、読み込む側に @use がずらりと並びます。そこで役立つのが _index.scss です。フォルダの中に _index.scss を置いておくと、フォルダ名を指定するだけで読み込めます。
// このフォルダの中身を、まとめて外に公開する
@forward "variables";
@forward "mixins";
@forward "functions";
// abstracts/_index.scss が読み込まれ、名前空間は abstracts になる
@use "../abstracts";
.button {
padding: abstracts.$space-md;
background-color: abstracts.$color-primary;
@include abstracts.mq(md) {
padding: abstracts.$space-md * 2;
}
}
ここで出てくる @forward は「読み込んで、そのまま外へ再公開する」ための命令です。@use が「自分が使うために読み込む」のに対し、@forward は「自分を読み込んだ相手に渡す」という役割の違いがあります。_index.scss は中継役なので @forward を使います。
| 書き方 | 意味 |
|---|---|
@use "variables" | 自分のファイル内で使うために読み込む |
@forward "variables" | 読み込んだ内容を、自分を読み込む側にも公開する |
@forward "variables" show $color-primary | 指定したものだけを公開する |
@forward "variables" hide $color-debug | 指定したものを除いて公開する |
@forward "button" as btn-* | 公開する名前に接頭辞を付ける |
ディレクトリ構成の例
分け方に決まったルールはありませんが、「抽象的なもの → 土台 → 部品 → ページ固有」の順に並べる構成がよく使われます。中規模のサイトなら、次のくらいの粒度から始めると扱いやすいはずです。
src/
├── style.scss # 入口。ここだけが CSS になる
├── abstracts/ # 出力されないもの(変数・mixin・関数)
│ ├── _index.scss
│ ├── _variables.scss
│ ├── _mixins.scss
│ └── _functions.scss
├── base/ # リセット・要素そのもののスタイル
│ ├── _index.scss
│ ├── _reset.scss
│ └── _typography.scss
├── layouts/ # ヘッダー・フッター・グリッドなど大枠
│ ├── _index.scss
│ ├── _header.scss
│ └── _footer.scss
├── components/ # ボタン・カードなど再利用する部品
│ ├── _index.scss
│ ├── _button.scss
│ └── _card.scss
└── pages/ # 特定ページ専用のスタイル
├── _index.scss
└── _contact.scss
| フォルダ | 入れるもの | CSS が出力されるか |
|---|---|---|
abstracts | 変数・mixin・関数 | されない(使われたときだけ) |
base | リセット、body や a のスタイル | される |
layouts | ヘッダー・フッター・グリッド | される |
components | ボタン・カード・フォーム部品 | される |
pages | 特定ページだけのスタイル | される |
入口となる style.scss では、出力順どおりに読み込みます。CSS は後に書かれたほうが優先されるため、読み込む順番がそのまま優先順位になります。リセットを最初に、ページ固有のスタイルを最後に置くのが基本です。
// 出力されない定義は先に
@use "abstracts";
// 以降は出力順 = 優先順位
@use "base";
@use "layouts";
@use "components";
@use "pages";
コンパイルは、入口のファイルと出力先を指定して実行します。--watch を付けると、保存するたびに自動で変換されます。
# 1回だけコンパイルする
$ npx sass src/style.scss dist/style.css
# 保存のたびに自動でコンパイルする
$ npx sass --watch src/style.scss dist/style.css
分割したあとにハマりやすいところ
変数が見つからないとエラーになる
Undefined variable というエラーが出たときは、そのファイル自身が @use していないことがほとんどです。かつての @import は、一度読み込めばどのファイルからでも変数が使えました。@use にはその性質がなく、変数を使うファイルごとに読み込みが必要です。
面倒に思えますが、これは「そのファイルが何に依存しているか」がファイルの先頭を見れば分かる、という利点の裏返しでもあります。なお同じファイルを複数箇所から @use しても、CSS への出力は1回だけです。重複を心配する必要はありません。
@use の位置でエラーになる
@use rules must be written before any other rules と表示されたら、@use よりも前にスタイルルールやコメント以外の記述がある状態です。ファイルの一番上に移動してください。複数の @use を書く場合も、まとめて先頭に並べます。
パーシャルなのに CSS ファイルができてしまう
アンダースコアの付け忘れです。variables.scss のままだと、コンパイル対象のフォルダを丸ごと指定している場合に variables.css が出力されます。読み込まれる側のファイルはすべて _ で始める、と統一しておけば起きません。
外から触られたくない変数がある
変数名や関数名を - または _ で始めると、そのファイルの中だけで使えるプライベートメンバーになります。$_internal-gutter のように書いておけば、@use した側からは参照できません。計算の途中で使うだけの値を隠すのに便利です。
まとめ
Sass のファイル分割は、アンダースコアで始まるパーシャルを作り、@use で読み込む、という2つの要素でできています。パーシャルは単体では CSS にならず、読み込んだ側の出力に組み込まれます。
フォルダごとに _index.scss を置いて @forward で中身をまとめておくと、読み込む側は @use "../abstracts" の1行で済みます。変数や mixin をまとめた abstracts フォルダを1つ用意するだけでも、見通しはかなり良くなります。
最初から細かく分ける必要はありません。style.scss が長くなってきたら変数を _variables.scss に出す、ボタンのスタイルがまとまったら _button.scss に移す、というように、困ったところから切り出していくのが現実的な進め方です。