Sass 再入門(その2:ファイルの書き方)

2021/04/24

前回、「Sass 再入門」の続きです。今回はファイルの書き方についてです。

コメント

Sass でもファイルにコメントを書くことができます。

単一行コメント

CSSでは、単一行コメントの // は使えませんが、Sass では使用することができます。 単一行コメントの内容は、CSSとして出力されません。

複数行コメント

複数行コメント /* */ の内容はデフォルトではCSSとして出力されますが、 Sass を圧縮モード(--style=compressed)で実行した場合(つまり minify した場合)、CSSとして出力されません。

但し、複数行コメントが /*! で始まる場合は、圧縮モードで実行した場合でも常にCSSとして出力されます。 ライセンスの情報などをコメントとして出力する必要がある場合などでは便利かもしれません。

演算子

Sass では、標準的な計算用の演算子(+-*/%)が使えます。 ピクセル値を取得してパーセンテージに変換するなどの操作を簡単に行うことができます。

変換元(.scss) 変換結果(.css)
article {
	width: 600px / 960px * 100%;
}
article {
	width: 62.5%;
}

変数

CSSでは何度も同じ値が登場します。 同じ値を再利用したいと思った場合に利用できるのが変数です。 $ で始まる名前に値を割り当てて変数を定義することができ、その定義した値を参照できます。 サイト全体で一貫性を保つのに便利です。

変換元(.scss) 変換結果(.css)
$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);

.alert {
	border: 1px solid $border-dark;
}
.alert {
	border: 1px solid rgba(198, 83, 140, 0.88);
}

スコープ

Sass の変数には参照できる範囲(スコープ)があります。 スタイルシートのトップレベルで宣言された変数はグローバル変数になり、どこからでもアクセスできます。 一方、ブロック(.scss では { } のこと)の中で宣言されたものはローカル変数になり、宣言されたブロックの中でのみアクセスできます。

ローカル変数は、グローバル変数と同じ名前で宣言することもできます。 その際、グローバル変数の値が誤って変更されることはありません。

変換元(.scss) 変換結果(.css)
$border-radius: 12px;

a {
	$border-radius: 24px;
	$border-color: red;

	border-radius: $border-radius;
	border: 1px solid $border-color;
}

div {
	$border-color: blue;

	border-radius: $border-radius;
	border: 1px solid $border-color;
}
a {
	border-radius: 24px;
	border: 1px solid red;
}

div {
	border-radius: 12px;
	border: 1px solid blue;
}

補間

変数の値をそのままの値としてではなく、クラス名などのセレクターの一部に使用したい場合や、値の一部として使用したい場合、変数を #{ } で囲む必要があります。

変換元(.scss) 変換結果(.css)
$name: topics;
$top-or-bottom: bottom;

.#{$name}-message {
	background-image: url("/img/#{$name}/bg.svg");
	position: absolute;
	#{$top-or-bottom}: 0;
	margin-#{$top-or-bottom}: 0;
	padding-#{$top-or-bottom}: 0;
}
.topics-message {
	background-image: url("/img/topics/bg.svg");
	position: absolute;
	bottom: 0;
	margin-bottom: 0;
	padding-bottom: 0;
}

入れ子構造(ネスト)

HTMLはタグが入れ子構造(ネスト)になっていて、階層構造になっています。一方、CSSはそうではありません。 また、CSSの文法的に同じセレクターが何度も登場してしまうため、記述するのが面倒という問題がありました。

Sass では、HTMLと同じ視覚的階層に従う方法でCSSセレクターをネストできます。 CSSの文法の重複部分を取り除き、さらにHTMLと似た構造で記述できることで、スタイルがHTMLのどの部分に適用されているかがわかりやすく、メンテナンス性が向上します。 とはいえ、過度にネストしすぎると、逆にメンテナンス性が失われて、保守が困難になる可能性があるので、そこは注意する必要があります。

変換元(.scss) 変換結果(.css)
nav {
	ul {
		margin: 0;
		padding: 0;
		list-style: none;
	}

	li {
		display: inline-block;
	}

	a {
		display: block;
		padding: 6px 12px;
		text-decoration: none;
	}
}
nav ul {
	margin: 0;
	padding: 0;
	list-style: none;
}
nav li {
	display: inline-block;
}
nav a {
	display: block;
	padding: 6px 12px;
	text-decoration: none;
}

親セレクター

Sass には、ネストされたセレクターで外部セレクターを参照することができる親セレクター & があります。 疑似クラスを追加したり、外部セレクターにサフィックスを追加したり、より複雑な方法で外部セレクターを再利用することができます。

変換元(.scss) 変換結果(.css)
.accordion {
	background: yellow;

	&:hover {
		background: orange;
	}

	:not(&) {
		opacity: 0.8;
	}

	&__copy {
		color: gray;

		&--open {
			display: block;
		}
	}
}
.accordion {
	background: yellow;
}
.accordion:hover {
	background: orange;
}
:not(.accordion) {
	opacity: 0.8;
}
.accordion__copy {
	color: gray;
}
.accordion__copy--open {
	display: block;
}

ミックスイン

ミックスインを使用すると、サイト全体で再利用するCSS宣言のグループを作成できます。 引数を渡すこともできるので、柔軟なミックスインを作ることができます。 ミックスインの適切な使用法は、ベンダープレフィックスです。

ミックスインを作成するには、@mixin を使用します。作成したミックスインを使用するには @include を使用します。

一見すると関数のように見えるかもしれませんが、関数はまた別に @function が存在しています。

変換元(.scss) 変換結果(.css)
@mixin transform($property) {
	-webkit-transform: $property;
	-ms-transform: $property;
	transform: $property;
}

.box {
	@include transform(rotate(30deg));
}
.box {
	-webkit-transform: rotate(30deg);
	-ms-transform: rotate(30deg);
	transform: rotate(30deg);
}

オプションの引数

通常、ミックスインは宣言するすべての引数を渡す必要がありますが、引数が渡されない場合に使用されるデフォルト値を定義することにより、引数をオプションにすることができます。 デフォルト値は、変数宣言と同じ構文の : を使用して設定します。

変換元(.scss) 変換結果(.css)
@mixin transform($property: rotate(45deg)) {
	-webkit-transform: $property;
	-ms-transform: $property;
	transform: $property;
}

.box {
	@include transform();
}
.box {
	-webkit-transform: rotate(45deg);
	-ms-transform: rotate(45deg);
	transform: rotate(45deg);
}

継承

ページをデザインするときに、あるクラスに別のクラスのすべてのスタイルと、それ自体の特定のスタイルを含める必要がある場合がよくあります。 例えば、BEM方法論では、ブロッククラスまたは要素クラスと同じ要素に属する修飾子クラスを推奨します。 ただし、これはHTML要素にクラス指定が複数含まれることになりHTMLが汚くなりますし、両方のクラスを含めるのを忘れたりもするでしょう。 マークアップに非セマンティックスタイルの懸念が生じる可能性があります。

例えば、BEM方法論に従えば下記のように、"message" と "message--success" の2つのクラス指定が必要になってしまいます。

HTML
<div class="message message--success">
	メッセージ
</div>
CSS
.message {
	border: 1px solid #ccc;
	padding: 10px;
}

.message--success {
	color: green;
}

しかし、これは Sass 上で @extend を使用すれば同じことができます。

@extend を使用すると、CSSプロパティのセットを1つのセレクターから別のセレクターに共有できます。 これにより、HTML要素に複数のクラス名を記述する必要がなくなります。 HTML要素のクラス指定でこの関係性をどうにかするのではなく、Sass 上で解決してしまえるということです。

例えば、下記のようにすると、HTML要素のクラス指定には "message--success" の1つだけを指定すれば、BEM方法論で2つのクラス指定したものと同じ結果にすることができます。

HTML
<div class="message--success">
	メッセージ
</div>
変換元(.scss) 変換結果(.css)
.message {
	border: 1px solid #ccc;
	padding: 10px;
}

.message--success {
	@extend .message;
	color: green;
}
.message, .message--success {
	border: 1px solid #ccc;
	padding: 10px;
}

.message--success {
	color: green;
}

プレースホルダーセレクター

拡張のみを目的としたCSSプロパティのセットを作成したい場合があります。 イメージ的に言えば、他のプログラミング言語でいうところの抽象クラス(abstract)に近いでしょうか。 その場合、% で始まる名前を付けることで作成することができます。 % を付けて作成したCSSプロパティのセットは、単体ではCSSに変換されません。 別の個所から @extend で読み込まれて初めてその内容が変換されます。

変換元(.scss) 変換結果(.css)
%message-shared {
	border: 1px solid #ccc;
	padding: 10px;
	color: #333;
}

.message--success {
	@extend %message-shared;
	border-color: green;
}

.message--error {
	@extend %message-shared;
	border-color: red;
}
.message--error, .message--success {
	border: 1px solid #ccc;
	padding: 10px;
	color: #333;
}

.message--success {
	border-color: green;
}

.message--error {
	border-color: red;
}

参考サイト

関連記事

CSS自体は楽しいものですが、長く運用していると、CSSファイルは巨大化し、複雑になり、メンテナンスが難しくなりがちです。CSSファイルは誰もメンテナンスできないなんていうプロジェクトに何度か遭遇したことがあります。巨大で複雑なCSSファイルをメンテナンスできるようにするには、どうすればよいでしょうか?そこで登場するの ...
前回、「Sass 再入門(その2:ファイルの書き方)」の続きです。今回はファイル分割についてです。別のファイルを読み込む(@use)Sass で便利だなと思う機能は、複数のファイルに分割できることでしょう。ファイルが分割できることで、1つのファイルが小さくなり、メンテナンスがしやすくなります。読み込まれる側のファイルと ...
最近の Web 界隈では、UX を高めるために、UI を JavaScript でガリガリ実装するというのが普通になってます。フロントエンドエンジニアなんていう職種が生まれるほど、この界隈は活発です。そこでフロントエンド開発でほぼ必須となるであろう Node.js と npm について少しまとめてみます。今更感がすごい ...

記事検索

最新記事

RSSフィード