【徹底解説】SCSSの書き方まとめ!基本を抑えてコーディング速度向上!

【徹底解説】SCSSの書き方まとめ!基本を抑えてコーディング速度向上!

この記事を書いた人

だいち

PENGIN BLOGメディア編集長。Web業界とは異業種の仕事をしながら、独学でWeb制作の世界に。副業でHP制作やコーディング代行、個人ブログの運営などに取り組み、現在はPENGINにてWebライティングやディレクションをしつつ、メディア運営全般を担当しています。(個人運営ブログ:https://daib-log.com/ )

SCSSは多機能なのでどこまで理解すればいいのかお悩みじゃないですか?

実務で使う範囲はそこまで多く無いですが、知らないと無駄に学習時間を使ってしまいます。

そこでこの記事では、コーディング代行などをしてきた筆者の経験から、実務で使う範囲と、学習中に知っておきたかった内容をまとめています。

記事を読み終えると、SCSSを使ううえで最低限必要な情報を知れるので、効率的に学習を進めることができますよ!

※「Sassの役割がぼんやりとしかわかってない!」という方は、先にこちらの記事に目を通しておきましょう!

SCSSとは

SCSSとはSassの記法です。(SCSSという言語はないです!)

SASS記法に馴染みが無い方も多いですが、SCSS記法はCSSに近い書き方ですので、初学者の方でも取り入れやすいという特徴があります。

現場でもSCSS記法の方が普及していますので、この記事で基本的な書き方を覚えておきましょう!

SCSSはコンパイルしないと使えませんが、CSSには無い便利な機能があるため、効率的にコーディングできます。

コンパイル方法については、当記事で2パターン紹介しているので、環境構築がまだな方は先に用意しておきましょう。

Sassのコンパイル方法

SCSSの基礎知識

演算について

SCSSではcalcを使わずに値を演算できます。

.class1 {
	width: 50 + 20;
}

// 単位が同じ
.class2 {
	width: 50px + 20px;
}

// 単位片方のみ指定
.class3 {
	width: 50 + 20px;
}
/* コンパイル後 */
.class1 {
  width: 70;
}

.class2 {
  width: 70px;
}

.class3 {
  width: 70px;
}

ただ長さの単位の種類が違う場合は計算できません。種類というのは「絶対値」と「相対値」の違いです。

「絶対値」と「相対値」の違いはこちらの記事内で触れてます。

演算の単位

  • 足し算(+)
  • 引き算( – )
  • 掛け算( * )
  • 割り算( / )
  • 剰余( % )
// 単位が違うのでコンパイルされない
.class4 {
	width: 50px + 20%;
}

上のように、絶対値であるpxと相対値の%を記述していると、コンパイルすることができません。

calcを使う必要がある場面

「絶対値」と「相対値」を組み合わせた計算をしたい枚はcalcを使う必要があります。

.class4 {
	width: calc(50% + 20px);
}

Sassのデータタイプ

Sassには値の種類がいくつかあります。名称まで覚えないといけないわけではないですが、考え方は知っておきましょう。

Number型

1 , 15 , 30px , 100% など

数値(単位を含む)はすべてNumber型です。

Color型

white , #ffffff , rgba(255,255,255,0.8) など

色の値はカラーネームや16進数であってもすべてColor型です。

String型

sass , 'SCSS' , "SASS" など

Number型、Color型以外のテキストはすべてString型です。また、クォーテーションに囲まれた文字列もString型になります。

Boolean型

true , false

true(真) , false(偽)の真偽値はBoolean型です。

Null型

null

空の値はNull型です。

List型

$list:"one","two","three";

カンマやスペース、カッコで区切ったものはList型です。Sassでは配列として変数に格納する時に使います。

Map型

$map: (key1: value1, key2: value2, key3: value3);

連想配列で任意の名前と値のペアが集まったものがMap型です。

コメントの書き方

.class {
	// SCSSのコメント →コンパイルされない
	margin: 0 auto;
	/* CSSでも使うコメント  →コンパイルされる */
	padding: 0 20px;
}
.class {
  margin: 0 auto;
  /* CSSでも使うコメント  →コンパイルされる */
  padding: 0 20px;
}

SCSSでは //(バックスラッシュ2つ)でコメントが書けます。

このコメントはコンパイルで残らないので、Sassファイルにだけ残しておきたい場合に使えます。

CSSファイルにも記録しておきたいコメントは /* */ で囲めば残せます。

ネスト(入れ子)の書き方

.class {
	.outer {
		padding: 10px 20px;
		.inner {
			width: 100%;
		}
	}
}

SCSSではセレクタを入れ子(ネスト)にできます。

/* コンパイル後 */
.class .outer {
  padding: 10px 20px;
}

.class .outer .inner {
  width: 100%;
}

CSSで詳細度を上げる場合、親要素のセレクタを重ねて記述しないといけませんが、ネストにすると記述量を減らすことができます。

HTMLと同じような階層構造で書ければ、直感的に分かりやすくもなります。

ポイント

ネストを深くしすぎるとCSSの詳細度がきつくなるので、現実的には2〜3階層程度に留めておいたほうが良いです。

&(アンパサンド)で親要素を参照

.class {
	margin: 30px;

	&--red {
		color: red;
	}
	&:first-of-type {
		margin-top: 0;
	}
	&:hover {
		opacity: .7;
	}
	&.is-click {
		transform: translateY(5px);
	}
}

ネスト内では親要素のセレクタを&(アンパサンド)として使えます。

同じセレクタ名を何度も書く手間を省けたり、親要素のBlock名が変更になった時に子要素のセレクタへもまとめて変更反映できるなど、効率化の点でメリットがあります。

ポイント

&で記述していると、エディタ内でセレクタ検索できなかったり、第三者から見るとHTMLの要素が特定しずらいというデメリットはあるので、使い所には気をつけましょう

@at-root

@at-rootを記述すると、入れ子の内側に記述したスタイルをルートに戻すことができます。

.class {
	.outer {
		padding: 10px 20px;

		@media (max-width: 480px) {
			padding: 0 10%;
			@at-root {
				.inner {
					width: 100%;
				}
			}
		}

	}
}
/* コンパイル後 */
.class .outer {
  padding: 10px 20px;
}

@media (max-width: 480px) {
  .class .outer {
    padding: 0 10%;
  }
  .inner {
    width: 100%;
  }
}

変数の書き方

SCSSではプログラミング言語ではおなじみの変数が使えます。(変数とは値や文字列など情報を格納できる箱のようなものです)

// 変数1
$base-color: black;
// 変数2
$accent-color: red;

「$変数名:値」の形で記述することで、変数名に値が格納でき、別場所で使いますことができるようになります。

.class {
	color: $base-color;
}
.class2 {
	color: $accent-color;
}
/* コンパイル後 */
.class {
  color: black;
}

.class2 {
  color: red;
}

呼び出す時は値に「$変数名」とすればそのまま呼び出せます。

ハイフンとアンダースコア

.variable {
	$text-color: red; // ハイフン
	color: $text_color; // アンダースコア
}
/* コンパイルOK */

SCSSの場合ハイフンとアンダースコアは同一と見なされるので、上の場合でも同一変数と認識されてコンパイルされます。

変数の有効範囲

変数には有効範囲(スコープ)があります。

宣言ブロック内(波括弧)でも変数を定義することができますが、その場合は定義したルール内でのみ参照可能なローカル変数となります。

宣言ブロック外に定義した変数はグローバル変数となり、基本的にどこでも使えますが、同じ変数名でローカル変数を定義するとその宣言ブロック内の値は上書きされます。

$variable-color: black; // グローバル変数
.variable {
	color: $variable-color; // グローバル変数→コンパイルOK
}

/* **************************** */
.variable2 {
	$variable2-color: red; // ローカル変数
	color: $variable2-color; // ローカル変数→コンパイルOK
}

/* **************************** */
.variable3 {
	$variable3-color: blue; // ローカル変数
}
.Variable3-inner {
	color: $variable3-color; // ローカル変数→コンパイルNG
}

上の例だと、ローカル変数「$variable3-color」は.variable3の宣言ブロックに定義されているため、.Variable3-innerでは参照できません。

!global フラグ

.variable3 {
	$variable3-color: blue !global; // ローカル変数 !global
}
.Variable3-inner {
	color: $variable3-color; // ローカル変数だけどコンパイルOKになる
}

!globalフラグをつけることでローカル変数でもグローバル変数のように扱えるようになります。

!default フラグ

// 変数設定
$color: black;
$color: red;

.variable {
	color: $color; // →コンパイル結果:red
}

同じ変数名がある場合、通常は下に記述されている変数が優先されます。

// 変数設定
$color: black;
$color: red !default;

.variable {
	color: $color; // →コンパイル結果:black
}

!defaultフラグは、同一変数名に値が設定されていない場合にのみ代入されるフラグです。

上の場合、1つめの変数$colorにすでに(black)という値が入っているため、!defaultフラグがついている変数値(red)では上書きしないようにできます。

ファイル分割をして上書きを前提にするディレクトリ構造にしている場合などに活用するシーンがある機能です。

インターポレーションについて

インターポレーション(補完)とは、値を文字列として扱うことのできる機能です。

対象を#{ }で囲みます。インターポレーションを使うと、文字列を代入した変数を呼び出すことも可能。

$variable: ".class";

#{$variable} {
	width: 50px;
}
/* コンパイル後 */
.class {
  width: 50px;
}

クラス名(文字列)を代入して呼び出したり、

$path: '../images/';
.img {
    background: url(#{$path}img.png);
}
/* コンパイル後 */
.img {
  background: url(../images/img.png);
}

ファイルの格納先などもインターポレーションを使えば呼び出せます。

制御構文の書き方

SCSSではプログラミング言語で使える制御構文が使えます。

if文

@if 条件A {
  // 条件Aの場合のスタイル
}
@else if 条件B {
  // 条件Bの場合のスタイル
}
@else {
  // 条件AでもBでもない場合のスタイル
}

条件分岐をさせる場合はif文を使います。

$if-style: true;
@if $if-style {
	.m-top {
		margin-top: 0;
	}
}

条件一致した場合にのみスタイルをあてることができます。

for文

// 開始から終了の数値を含んだ間で繰り返しの処理
@for 変数名 from 開始の数値 through 終了の数値 {
   // 繰り返しの処理内容
}

// 開始から終了の数値を含まない間で繰り返しの処理
@for 変数名 from 開始の数値 to 終了の数値 {
   // 繰り返しの処理内容
}

決めた期間内で繰り返し処理をする場合for文が使えます。

// 5から10までの間で繰り返す
@for $i from 5 through 10 {
 // 繰り返しの処理内容
	.hp_mt#{$i * 10} {
		margin-top: 10px * $i;
	}
}

上のfor文は、5×10(=50)から10×10(=100)までの間で繰り返し計算処理します。

/* コンパイル後 */
.hp_mt50 {
  margin-top: 50px;
}

.hp_mt60 {
  margin-top: 60px;
}

.hp_mt70 {
  margin-top: 70px;
}

.hp_mt80 {
  margin-top: 80px;
}

.hp_mt90 {
  margin-top: 90px;
}

.hp_mt100 {
  margin-top: 100px;
}

コンパイルすると繰り返し処理結果が出力されます。for文を使うことで規則的なスタイルをまとめて作成できます。

while文

@while 繰り返す条件 {
  // ①繰り返す処理(スタイル)
  // ②繰り返しの条件
}

while文も繰り返し処理で使いますが、繰り返し条件が true(真)である間繰り返し続けます。

$i: 4;
@while $i < 10 {
  // ①繰り返すスタイル
	.hp_mt#{$i * 10} {
		margin-top: 10px * $i;
	}
  // ②繰り返しの条件
	$i: $i + 1;
}

上のwhile文は、10を超えているか真偽を判定しながら、10になるまで変数$iに1ずつプラスしながら繰り返します。

/* コンパイル後 */
.hp_mt50 {
  margin-top: 50px;
}

.hp_mt60 {
  margin-top: 60px;
}

.hp_mt70 {
  margin-top: 70px;
}

.hp_mt80 {
  margin-top: 80px;
}

.hp_mt90 {
  margin-top: 90px;
}

.hp_mt100 {
  margin-top: 100px;
}

each文

@each 変数名 in リスト {
  処理内容
}

each文は、カンマやスペース、カッコなどで区切られたリスト(複数データ)の値を繰り返します。

@each $class in value1, value2, value3 {
  .#{$class}-img {
    background-image: url(./image/#{$class}.png);
  }
}

処理内容の中でvalue1、value2、value3を繰り返させます。

$values: value1, value2, value3;

@each $class in $values {
	.#{$class} {
		background-image: url(../images/bg_#{$class}.png);
	}
}

上のように、リストは変数に格納するとコードも少しスッキリします。

/* コンパイル後 */
.value1 {
  background-image: url(../images/bg_value1.png);
}

.value2 {
  background-image: url(../images/bg_value2.png);
}

.value3 {
  background-image: url(../images/bg_value3.png);
}

パーシャルと読み込み方

ファイルは複数分かれていても、@importでまとめてコンパイルすることができます。

パーシャル

ディレクトリ写真

ただファイルを分割しただけだと、すべてCSS ファイルとしてコンパイルされてしまい、不要なファイルが生成されてしまいます。

この状況を防ぐため、画像のように、ファイル名の先頭にアンダースコア( _ )を付けることで、CSS ファイルを生成しないようにすることができます。

この機能がパーシャルです。

これにより「.scssファイルを分割して管理しつつ、生成するCSS ファイルは1つだけにする」ことが可能になります。

// style.scss
// *****************************

// setting
@import "setting/size";
// mixin
@import "mixin/mixin";
// function
@import "function/function";
// base
@import "base/base";
// layout
@import "layout/layout";
// module
@import "module/nav";

パーシャルはCSSファイルに変換されないため、最終的に CSS ファイルに変換させるメインのファイルを作って、まとめて読み込むようにします。

この時「@import ファイルパス」で呼び出します。読み込むパスには先頭のアンダースコア(_)をつけなくとも読み込めます。

ここまで@importについて触れましたが、@importは実は2022年10月にサポートが終了する予定です。

変わりの機能として@useと@forwardという2つのルールができています。@import・@useについてはこちらの記事でしっかりと解説してます!

>> SCSSの@importは廃止に!?@useとの違いについて解説!

mixin

@mixin color($color: #333) {
  color: $color;
}

mixinはスタイル一式を格納することができる機能で、「@mixin mixin名」とすることで作成できます。mixin名は任意で決められますが、数字から始まる名前はつけられません。

上の例のように値を変数にして、()内に変数に対する引数を設定することもできます。

この例だと「#333」をデフォルトに設定してます。

// 呼び出し時
.text {
  @include color();
}
/* CSSコンパイル後 */
.text {
  color: #333;
}

「@include mixin名( )」と記述すればmixinのスタイルを呼び出すことができます。

@includeの( )に何も指定しないとデフォルトの値が呼び出されますし、別で指定することもできます。

詳しくはこちらの記事で解説しています。

mixin内にルールを渡す@content

@content は、ルールセットやスタイルをミックスイン内に渡す機能です。

@mixin tab() {
	@media screen and (max-width: 768px) {
		@content;
	}
}

.class {
	margin: 0 auto;
	padding: 0 20px;
	
	@include tab {
		width: 50%;
	}
}

ミックスインの中に @content を記述することで、スタイルをその場所に展開させることができます。

.class {
  margin: 0 auto;
  padding: 0 20px;
}

@media screen and (max-width: 768px) {
  .class {
    width: 50%;
  }
}

@include を使ってスタイルを記述すると、 @content を記述した場所にそのコンテンツが展開されます。

関数

Sassにはスタイルを簡単に作れる関数や、独自で関数が作成できる機能が用意されています。

詳しくはこちらの記事で解説しています。

この記事ではよく使われる内容だけ抜粋して解説します。

rgba()

rgba($color, $alpha)

rgba()はカラー指定ができる関数の中で、透明度を指定できる関数です。

.class {
	background: rgba($color: #000, $alpha: .7);
}
/* コンパイル後 */
.class {
  background: rgba(0, 0, 0, 0.7);
}

round()

round($number)

round()は小数点以下を四捨五入できる関数です。

.class1 {
	width: round($number: 33.33%);
}

$width: 50%;
.class2 {
	width: round($width / 3);
}
/* コンパイル後 */
.class1 {
  width: 33%;
}

.class2 {
  width: 17%;
}

map-get()

map-get($map, $key)

map-get()はキー($key)の値を取得する関数で、Map型のデータタイプから値を取り出します(指定したキーが存在しなければnullを返します)

// Map型の変数「mq-breakpoints」を定義
$mq-breakpoints: ("sm": 599px, "md" : 780px , "lg" : 1080px);

// 「maxmq」というmixinを定義(初期値はsmで設定)
@mixin maxmq($breakpoint: sm) {
// max-widthの値にmap-get関数で変数と値を取得
	@media screen and (max-width: #{map-get($mq-breakpoints, $breakpoint)}) {
		@content;
	}
}

// 呼び出し
.class {
	@include maxmq(md) {
		width: 33.3%;
	}
}
/* コンパイル後 */
@media screen and (max-width: 780px) {
  .class {
    width: 33.3%;
  }
}

function(自作関数)

functionは任意の名前で処理内容を自作することができる機能です。

mixinがスタイル一式を返しすことに対し、functionは値を返します。

@function 関数名() {
	@return 戻り値;
}

「@function 関数名」として処理内容を記述します。実行させる内容は@returnで返します。

.class {
	プロパティ:関数名();
}

実行する時は値に「関数名()」とするだけで呼び出せます。

関数名に( )で引数を設定し、初期値を渡しておくこともできます。(その場合は呼び出し時に引数の値を記述する必要があります)

$baseFontsize: 16;

// 「rem」という独自関数を作成
@function rem($pixels) {
	@return $pixels / $baseFontsize * 1rem;
}

上の例は、remを手計算せず、px感覚で扱うための関数です。

baseFontsize(16)に1remをかけて「16rem」という値を出し、引数で渡したpxの数値で割ることで、計算結果の値をremに変換します。

.class {
	font-size: rem(24);
}
/* コンパイル後 */
.class {
  font-size: 1.5rem;
}

値に関数名remと書き、( )内に引数としてpx値の数値を記述することで、値をremに変換しています。

まとめ

今回は実務でも使えるSCSSの基礎的な知識から書き方までを解説しました。

今回紹介した中でも、

  • ネスト
  • mixin
  • パーシャル

この3つは特に大事なので、まず初めに使えるようになっておきましょう!

Sass自体にはまだたくさんの機能がありますのが、あせらず、必要な時に一つずつ知っていけば大丈夫です!