Sass 再入門(その3:ファイル分割)

2021/04/25

前回、「Sass 再入門(その2:ファイルの書き方)」の続きです。今回はファイル分割についてです。

別のファイルを読み込む(@use)

Sass で便利だなと思う機能は、複数のファイルに分割できることでしょう。 ファイルが分割できることで、1つのファイルが小さくなり、メンテナンスがしやすくなります。 読み込まれる側のファイルと、読み込む側のファイルで書き方のルールが異なります。

読み込まれる側のファイル

読み込まれる側のファイルのファイルは、ファイル名の先頭に "_"(アンダーバー)を付けた名前になります。 例えば、"_partial.scss" のようになります。

このファイル名の先頭のアンダーバーは、ファイルが部分的なファイルにすぎず、CSSファイルに生成されないという意味があります。 つまり、このファイル単体では変換されないということです。 別のファイルから読み込まれて初めてその内容が変換されることになります。

読み込む側のファイル

読み込む側のファイルでは、どのファイルを読み込むかを指定する必要があります。どのファイルを読み込むかを指定するには @use を使います。 読み込まれる側のファイルには、ファイル名の先頭にアンダーバーを付けるというルールがありましたが、 読み込む側のファイルで指定する際には、そのファイル名の先頭のアンダーバーや、ファイルの拡張子は付けず、その名前だけを指定します。

Sass のファイルの拡張子は .sass と .scss の2種類ありますが、どちらのファイルを読み込むかは自動的に解決されるので、拡張子を指定する必要はないということです。 ちなみに同じ場所に同じ名前で .sass と .scss ファイルの2ファイルあった場合はエラーとなります。

/* _partial.scss もしくは、_partial.sass を読み込む */
@use "partial";

読み込まれる側のファイルが、別のディレクトリにある場合でも、アンダーバーと拡張子は除いた形で指定します。

/* foo/bar/_partial.scss もしくは、foo/bar/_partial.sass を読み込む */
@use "foo/bar/partial";

読み込まれる側のファイル(_partial.scss) 変換結果(main.css)
a {
	display: block;
	padding: 6px 12px;
}
a {
	display: block;
	padding: 6px 12px;
}

div {
	margin: 0;
	padding: 0;
}
読み込む側のファイル(main.scss)
@use "partial";

div {
	margin: 0;
	padding: 0;
}

別のファイルの変数やミックスインなどを使用する

読み込まれる側のファイルに記載された変数やミックスインなどを、読み込み側のファイルでも使用することもできます。 その場合、@use のファイル名(名前空間名)をプレフィックスとして . でつなげて指定します。

読み込まれる側のファイル(_partial.scss) 変換結果(main.css)
$color: red;
div {
	color: red;
}
読み込む側のファイル(main.scss)
@use "partial";

div {
	color: partial.$color;
}

別のファイルの変数やミックスインなどを使用できないようにする

読み込まれる側のファイルに記載された変数やミックスインなどを、読み込み側のファイルでは使用できないようにしたい場合があります。 その場合は、定義する際の名前を - もしくは _ で始めると、その要素はそのファイル内でのみしか使用できなくなります。

読み込まれる側のファイル(_partial.scss) 変換結果(main.css)
$color: red;
$-border-color: green;

a {
	color: $color;
	border-color: $-border-color;
}
a {
	color: red;
	border-color: green;
}

div {
	color: red;
}
読み込む側のファイル(main.scss)
@use "partial";

div {
	color: partial.$color;
}

名前空間名を変更する

@use で読み込まれるファイルは、名前空間を持っています。 この名前空間があることで、別のファイルの変数などを指定する際に、どのファイルのものなのか判別できるようになります。 デフォルトでは、読み込んだファイル名がそのまま名前空間名となるのですが、 ディレクトリが異なる同じ名前のファイルを読み込もうとした場合、同じ名前空間名になってしまうため、名前空間名を変更する必要が出てきます。 名前空間名を変更するには、@use を使用する際に as で別名を指定します。

読み込まれる側のファイル1(foo/_partial.scss) 変換結果(main.css)
$color: red;
a {
	color: red;
}

div {
	color: blue;
}
読み込まれる側のファイル2(bar/_partial.scss)
$color: blue;
読み込む側のファイル(main.scss)
@use "foo/partial" as foo_partial;
@use "bar/partial" as bar_partial;

a {
	color: foo_partial.$color;
}

div {
	color: bar_partial.$color;
}

別のファイルの変数の値を変更する

読み込まれる側のファイルに定義している変数に !default キーワードを付けておくと、 読み込み側のファイルで @use で読み込む際に with を付けて指定することで、その値を書き換えることができます。 !default が付いていない変数は、読み込み側のファイルでは書き換えられません。 これは、読み込まれる側のファイルを変更することなくライブラリのように使いまわしたい場合などに便利です。

読み込まれる側のファイル(_partial.scss) 変換結果(main.css)
$color: red !default;
$border-color: green !default;
$border-radius: 0.1rem;

a {
	color: $color;
	border-color: $border-color;
	border-radius: $border-radius;
}
a {
	color: blue;
	border-color: aqua;
	border-radius: 0.1rem;
}

div {
	color: blue;
	border-color: aqua;
	border-radius: 0.1rem;
}
読み込む側のファイル(main.scss)
@use "partial" with (
	$color: blue,
	$border-color: aqua,
);

div {
	color: partial.$color;
	border-color: partial.$border-color;
	border-radius: partial.$border-radius;
}

ファイルを階層構造にする(@forward)

ファイルを分割していると、分割したファイルが大量になってきて、その扱いに困ってくるかもしれません。 例えば、読み込み側のファイルでは、@use の記述が大量に必要になってくるでしょう。 そこで、親、子、孫ファイルなどのように階層構造にしたいと思うでしょう。 しかしながら、@use では、1階層下のファイルのモジュールの名前空間しか使えないという制限があります。 そこで登場するのが @forward です。

孫ファイル(_grandchild.scss) 変換結果(parent.css)
$color: red;

a {
	color: $color;
}
a {
	color: red;
}

div {
	color: red;
}
子ファイル(_child.scss)
// このファイルで @use を使ってしまうと、
// 孫ファイルで定義された変数やミックスインなどが、
// 親ファイルで使えないため、
// @forward を使用する必要がある

@forward "grandchild";
親ファイル(parent.scss)
@use "child";

div {
	color: child.$color;
}

名前空間名にプレフィックスを追加する

名前空間名は短くて単純な名前の方がわかりやすいですが、階層構造にした場合は、どのファイルの値なのかが逆にわかりづらくなるかもしれません。 そこで、@forward で親ファイルに転送される名前空間名にプレフィックスを追加するオプションがあります。 プレフィックスを追加するには、@forward を使用する際に as <prefix>-* の形式で指定できます。

孫ファイル(_grandchild.scss) 変換結果(parent.css)
$color: red;
div {
	color: red;
}
子ファイル(_child.scss)
@forward "grandchild" as grandchild-*;
親ファイル(parent.scss)
@use "child";

div {
	color: child.$grandchild-color;
}

可視性を変更する

孫ファイルにある全ての変数やミックスインなどを、親ファイルに公開したくない場合があります。 デフォルトでは全て公開されているのですが、一部だけを公開にしたり、一部だけを非公開にしたりするように指定することができます。

一部だけを公開にする場合は、@forward を使用する際に show <members...> の形式で指定できます。

一部だけを非公開にする場合は、@forward を使用する際に hide <members...> の形式で指定できます。

どちらの形式でも、変数やミックスインなどの名前を ,(カンマ)区切りで指定します。

孫ファイル(_grandchild.scss) 変換結果(parent.css)
$color: red;
$border-color: green;
$background-color: blue;
div {
	color: red;
	border-color: green;
}
子ファイル(_child.scss)
// 孫ファイルのうち、
// $color と $border-color だけが使えるように制限
// $background-color は使えない

@forward "grandchild" show $color, $border-color;
親ファイル(parent.scss)
@use "child";

div {
	color: child.$color;
	border-color: child.$border-color;
}

孫ファイルの変数の値を変更する

@use と同じように、!default キーワードが付いている変数は、@forward を使用する際に with を付けて指定することで、その値を書き換えることができます。

孫ファイル(_grandchild.scss) 変換結果(parent.css)
$color: red !default;
$border-color: green !default;
$border-radius: 0.1rem;

a {
	color: $color;
	border-color: $border-color;
	border-radius: $border-radius;
}
a {
	color: orange;
	border-color: yellow;
	border-radius: 0.1rem;
}

div {
	color: orange;
	border-color: yellow;
	border-radius: 0.1rem;
}
子ファイル(_child.scss)
@forward "grandchild" with (
	$color: green !default,
	$border-color: yellow,
);
親ファイル(parent.scss)
@use "child" with (
	$color: orange,
);

div {
	color: child.$color;
	border-color: child.$border-color;
	border-radius: child.$border-radius;
}

参考サイト

関連記事

CSS自体は楽しいものですが、長く運用していると、CSSファイルは巨大化し、複雑になり、メンテナンスが難しくなりがちです。CSSファイルは誰もメンテナンスできないなんていうプロジェクトに何度か遭遇したことがあります。巨大で複雑なCSSファイルをメンテナンスできるようにするには、どうすればよいでしょうか?そこで登場するの ...
前回、「Sass 再入門」の続きです。今回はファイルの書き方についてです。コメントSass でもファイルにコメントを書くことができます。単一行コメントCSSでは、単一行コメントの // は使えませんが、Sass では使用することができます。単一行コメントの内容は、CSSとして出力されません。複数行コメント複数行コメント ...
最近の Web 界隈では、UX を高めるために、UI を JavaScript でガリガリ実装するというのが普通になってます。フロントエンドエンジニアなんていう職種が生まれるほど、この界隈は活発です。そこでフロントエンド開発でほぼ必須となるであろう Node.js と npm について少しまとめてみます。今更感がすごい ...

記事検索

最新記事

RSSフィード