【初学者必見】SCSSのmixinを徹底解説&おすすめスニペット紹介!

【初学者必見】SCSSのmixinを徹底解説&おすすめスニペット紹介!

この記事を書いた人

だいち

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

「コーディングってどうやったら速くなるんだろう?」とお悩みじゃないですか?

Sassのmixinを使えば効率化できると聞いたことはあるけど、いまいち利便性がわからない…という方もいます。

mixinはコピペでもいいんですが、自分流にカスマイズできないと、実は最大限効果を発揮できません。

この記事では、自分に合ったmixinが作れるようになるための基礎知識から、現場で使える便利なmixinスニペットを紹介します!

記事を読み終えると、mixinの理解度が深められることで爆速コーディングへの一歩を踏み出せますよ!

mixinとは

プロパティや値をセットにしてまとめることができる機能です。

@mixin mixin名 {
  プロパティ: 値;
}

@mixin mixin名 として、{ }内にまとめたいプロパティと値を記述します。これだけでアイテム化されます。

mixinの基本的な書き方

まとめたmixinは、@include mixin名と記述するだけで呼び出せます。

@mixin p-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50% , -50%);
}
div {
  @include p-center;
}
/* コンパイル結果(style.css) */
div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50% , -50%);
}
mixinを使うメリット
  • サイト内で使い回しをする共通のスタイルであれば、何度も同じコードセットを書く手間が省ける
  • 修正が入った際などmixinの一箇所だけ修正すればまとめて変更できる

mixinで使える文字について

@mixin alphabet
@mixin alpha-bet
@mixin alphabet123
@mixin カタカナ
@mixin ひらがな
@mixin 漢字

カタカナや漢字、ハイフンなどはmixinの文字として使用することができます。

@mixin 123alphabet
@mixin --shadow
@mixin alpha@bet

ただ上記のように、、、

  • 数字から始まる
  • 連続で続くハイフンから始まる
  • @などの記号

これらは使えないので注意が必要です。

mixinの基本的な使い方

ここからはもっとmixinを便利に、柔軟性を上げるための基本的な使い方を紹介します。

引数を使う

mixinでは引数(ひきすう)を使うことができます。

プログラミングで使われる言葉なので、「引数….とは…?」となっている方もいるかもしれません。

引数をものすごく簡単に言うと、「セットされた処理内容に渡す値」のことです。(※引き算的な意味合いではないですよ!)

当記事であればmixin=セットされた処理内容で、引数という値を渡すことで、mixinで処理される内容が変わり結果をコントロールすることができるようになります。

(ざっくり)引数とは
  • mixin = 飲み物の自動販売機
  • 引数 = 投入するお金(100円や150円)

入れる金額(引数)によって購入できるジュース(結果)が変わる、みたいな感じでイメージしてください!

※プログラミングではmixinに限らず、関数など様々な場面で引数が使われますが、考え方は同じです。

@mixin mixin名($引数) {
  //スタイルを定義
}

セレクタ {
  @include mixin名($引数);
}

mixin名($引数)と書いてmixinを作り、呼び出す際はinclude mixin名($引数)と書くことで使えます。

@mixin base-color($color) {
  color: $color;
}

p {
  @include base-color(#333333);
}

たとえば上記mixinの場合、

mixinで引数を使う説明
  1. プロパティはcolorを設定するけど、値は柔軟に変えたいので変数にしておこう
  2. 値は呼び出し時に決めるので、mixinには引数(プロパティの値=変数)が必要だ
  3. 呼び出し時に初めて値を指定する

引数を使ったmixinを作る時(使う時)は、こんな感じのイメージですね。

呼び出し時の値を変えると、コンパイルされる値も変えることができます。

また、この書き方の場合、呼び出し時( )内に引数の値を書いてないとコンパイルエラーになります。(値の指定をしていないので当然ではありますが)

@mixin base-color($color) {
  color: $color;
}

p {
// プロパティの値がどこにも指定されてないのでエラーになる!
  @include base-color; 
}
引数を使うメリット

「プロパティはまとめておきたいけど、値は使う場所で切り替えたい」

こんなmixinを作りたい時は引数が活用できます!

引数に初期値を指定

@mixin base-color($color:#333333) {
  color: $color;
}

引数に対して値の初期値を決めておくこともできます。

p {
  @include base-color;
}

/* コンパイル結果(style.css) */
p {
  color: #333333;
}

この場合は、呼び出し時に値を指定しなくても、初期値がコンパイルされます。

あくまで初期値なので、呼び出し時に異なる値を指定することで上書きすることもできます。

p {
  @include base-color(#ffffff);
}

/* コンパイル結果(style.css) */
p {
  color: #ffffff;
}

元々作っていたmixinをbase-color($color:#333333)と引数を与えた形でセットしているので、上のような記述が成立します。

引数に初期値を与えておくメリット

「ある程度は値が共通だけど、場所によって変えることがある」

こんなケースで使い回す場合のmixinには引数に初期値を設定しておくといいでしょう。

複数の引数を定義

@mixin base($color,$w-num,$h-num) {
  color: $color;
  width: $w-num;
  height: $h-num;
}

複数の値を変数化すれば、その数だけ引数に渡しておくことができます。

div {
  @include base(#333333,600px,400px);
}

/* コンパイル結果(style.css) */
div {
  color: #333333;
  width: 600px;
  height: 400px;
}

呼び出す際は、初期値を決めていなければ引数に対する値をカンマ区切りで指定すればOKです。

コンパイル時は、呼び出し時に指定した順番通りに値がコンパイルされるため、mixinの引数に渡した順番と同じになるようにしましょう。(ズレるとプロパティに対する値がおかしくなることがあります)

引数が複数あっても、それぞれ初期値を指定しておくことができます。

@mixin base($color:red,$w-num:300px,$h-num:300px) {
  color: $color;
  width: $w-num;
  height: $h-num;
}
div {
  @include base;
}

/* コンパイル結果(style.css) */
div {
  color: red;
  width: 300px;
  height: 300px;
}

こちらも上と同様、値を上書きすることができます。

特定の引数の値だけ上書き

複数の引数を指定した場合、「特定のプロパティ値だけ変えたい」というケースもあると思います。

その場合、

@mixin base($color:red,$w-num:300px,$h-num:300px) {
  color: $color;
  width: $w-num;
  height: $h-num;
}

div {
  @include base($w-num:600px);
}

/* コンパイル結果(style.css) */
div {
  color: red;
  width: 600px; /* 初期値300pxが上書きされてる */
  height: 300px;
}

このように呼び出し時、該当の引数と値だけ個別に指定すればOKです。

可変長引数(…)で指定

mixinは基本、引数1つに対して値一つしか指定できません。そうなると、値を複数指定できるプロパティを使いたい時に困ります。(box-shadowやtext-shadow、font-familyなんかが該当します)

@mixin mixin-box($box) {
  box-shadow: ($box);
}

// ひとつのプロパティに対して複数の値を指定しているためエラーになります!
div {
  @include mixin-box(3px 3px #333, 1px 1px #888);
}

そんな時に可変長引数を使います。可変長引数は(…)とカンマ3つをつける指定のことです。

@mixin mixin-box($box...) {
  box-shadow: ($box);
}

div {
  @include mixin-box(3px 3px #333, 1px 1px #888);
}

/* コンパイル結果(style.css) */
/* 可変長引数を使っているため値がそのままコンパイルされる! */
div {
    box-shadow: 3px 3px #333, 1px 1px #888;
}

引数の後ろにカンマ3つをつけるだけで、カンマ区切りの値もそのままコンパイルすることができます。

また、プロパティの特性に限らず、可変長引数を使うテクニックもあるので紹介します。

@mixin base($color,$w-num,$h-num) {
  color: $color;
  width: $w-num;
  height: $h-num;
}

複数の引数が与えられていて、初期値も設定されてないmixinにたいして、

$values : red, 300px,300px;

カンマ区切りで値だけ渡した変数($values)を用意しておき、

div {
  @include base($values...);
}

/* コンパイル結果(style.css) */
div {
  color: red;
  width: 300px;
  height: 300px;
}

呼び出し時に変数($values)を引数で指定して可変長引数を使えば、そのまま値をコンパイルさせることもできます!

Sassの機能を使ってmixinをレベルアップさせる

ここからは他のSassの機能と組み合わせることでより実践的になるmixinの使い方をご紹介していきます。

@ifでスタイルを切り分ける

与える引数で処理内容自体を切り替えて使いたい場合は@ifを使います。

@mixin column($sp:false) {
	display: flex;
	@if($sp) {
		flex-direction: column;
	}
}

初めて@ifを見る方には分かりづらいかもしれませんので、細かく説明していきます。

column($sp:false)

これはcolumnというmixin名に対して、$spという変数で無ければ(false)という引数を与えています。

@if($sp) {
	flex-direction: column;
}

さらに@ifを使い、引数が$spだった場合のセットを作っています。

つまりmixinを呼び出す時引数が「spだったらflex-direction: columnを与える」という条件式を作っています。

実際に呼び出してみます。

// 引数(sp)を与えなければ
div {
	@include column();
}
/* コンパイル結果(style.css) */
div {
  display: flex;
}

// 引数(sp)を与えたら
div {
	@include column(sp);
}
/* コンパイル結果(style.css) */
div {
  display: flex;
  flex-direction: column;
}

こんな感じで引数に指定する内容次第で処理内容を変えたいmixinを作るのに便利なのが@if式です。

@contentでコンテンツブロックを渡す

@contentはmixinにたいしてコンテンツブロックを渡すための機能です。コンテンツブロックは@contentを記述した箇所で展開されます。

いまいち分かりづらいと思うので実例で見てみましょう。

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

上の方で2種類のメディアクエリをmixin化してます。そしてメディアクエリの{ }内に@contentを指定しています。

div {
	margin: 0 auto;
	padding: 0 20px;
	width: 33.3%;
	
	@include tab {
		width: 50%;
	}
	@include sp {
		width: 100%;
	}
}

普通のmixinと同じく@includeで呼び出してみると、

/* コンパイル結果(style.css) */
div {
  margin: 0 auto;
  padding: 0 20px;
  width: 33.3%;
}

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

@media screen and (max-width: 599px) {
  div {
    width: 100%;
  }
}

このようにコンパイルされます。

メディアクエリ{ }というワンセットに@contentを指定することで、mixinで呼び出すセレクタに対してコンテンツブロックが渡され、セレクタ全体を囲む形で展開させることができます。

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

/* セレクタの中でmixinを呼び出しているけど */
div {
	@include tab {
		width: 50%;
	}
}

/* @contentの位置にセレクタからのワンセットが展開される */
@media screen and (max-width: 768px) {
  div {
    width: 50%;
  }
}

@extendとの違い

別のところで指定したスタイルセットを継承して呼び出せる機能として「extend」というものもあります。

mixinと少し用途が似ているので比較されることもありますが、ここで違いを触れておきます。

.box {
  background-color: #000;
}

.extendBox {
  @extend .box;
}

たとえば上のようにdiv{ 〜 }で作ったルールセットがある場合、他のセレクタで@extendとして継承したい要素(上だったら.box)を指定すると、

/* コンパイル結果(style.css) */
.box, .extendBox {
  background-color: #000;
}

このようにスタイルを継承してコンパイルさせることができます。

また、@extendは入れ子になっているすべてのスタイルも継承します。

.box {
  background-color: #000;
	.box-child {
		width: 100%
	}
}

.extendBox {
  @extend .box;
}

上のように.boxの下層に別のセット(.box-childクラス)を記述していたとしても、

/* コンパイル結果(style.css) */
.box, .extendBox {
  background-color: #000;
}
.box .box-child, .extendBox .box-child {
  width: 100%;
}

ネストされているスタイルごとまとめて継承してコンパイルします。

@extendは何度も同じスタイルを記述する作業をカットすることができる便利機能ではありますが、注意点もあります。

上の例であげたように入れ子になったすべてのスタイルもグルーピングしてコンパイルするため、階層が深くなってくると結果的にコードが煩雑になりがちです。

また、本来.boxクラスだけで良かったものの、@extendを使うために.box-childというクラスと、呼び出し用の.extendBoxというクラスも記述することで、HTMLとは関連性のない無駄なCSSを生成しています。

もしmixinだったら、

@mixin box($box-child:false) {
  background-color: #000;
	@if($box-child) {
		width: 100%
	}
}

.box {
  @include box(box-child);
}

@ifでbox-childという変数を条件分岐に使えば、

/* コンパイル結果(style.css) */
.box {
  background-color: #000;
  width: 100%;
}

無駄なクラスなど生成せずにコンパイルすることができます。

@mixinと@extendの違い
  • mixin・・・引数が使える、コードがグルーピングされない、呼び出し時は都度記述が必要
  • extend・・・引数は使えない、コードがグルーピングされる、呼び出しは一度にまとめられる

どちらも一長一短がありますが、僕は@extendを現場で使ったことはありません…。引数で値を柔軟に変えられることや、コンパイルされるCSSのことを考えると、@mixinでも十分じゃないかな、と”個人的には”思います。

シーンによって使い分けられるのが一番なので、@extendの特性を理解したうえで活用できる場所で試してみるのもよいかと思います!

おすすめmixinスニペット集

ここでは実際に僕が使っているmixinを一部紹介します!

様々な書籍や有益な記事を参考にさせていただいた内容から、独自に作成したものまであるので、良かったら参考にしてみてください!

フォント周り簡単設定

フォント周りの指定は、慣れない内だと漏れが起こりやすいです。

CSSで書く時はデザインカンプの数値を一度計算しないといけないプロパティもあります。

デザインカンプの値の説明
XDの場合

line-height

// line-height
@mixin l_height($pixels , $height) {
	font-size: $pixels * 1px;
	line-height: $height / $pixels;
}

// 呼び出し例
.class {
	@include l_height(18 , 30);
}

デザインカンプに記載の数値を入力する際、それぞれのプロパティを記述する手間を省きます。

引数にfont-sizeとline-height(行送り)の値を入力するだけでそれぞれコンパイルされます。

letter-spacing

// letter-spacing
@mixin l_spacing($spacing) {
	letter-spacing: ($spacing / 1000 ) + em;
}

// 呼び出し例
.class {
	@include l_spacing(200);
}

letter-spacingの短縮mixinです。

文字間はcssで指定する場合、文字サイズに対する割合で指定することが一般的ですが、毎回計算するのがメンドウなのでmixin化させています。

トラッキングの数値をそのまま入力すればOKです。

一括指定

フォント周りのプロパティを一括で指定するmixinです。

@mixin f_around($pixels, $height: false, $weight: false , $spacing: false) {
	font-size: $pixels * 1px;

	@if $weight {
		font-weight: $weight;
	}

	@if $height {
		line-height: $height / $pixels;
	}

	@if $spacing {
		letter-spacing: ($spacing / 1000) * 1em;
	}
}

// 呼び出し例
// @include f_around(フォントサイズ, 行送り , 太さ, トラッキング)

font-sizeだけは引数に指定する必要があります。それ以外の数値で順番通りに指定しない場合、飛ばす箇所はfalseと入力すればOKです。

IEで游ゴシックのフォントがズレるバグ対策

IEで游ゴシックを使うと若干上にズレるバグが発生します。

@mixin yu_lineHeight($paddingTop , $paddingRight , $paddingBottom , $paddingLeft) {
	@at-root {
			_:-ms-lang(x)::-ms-backdrop , & {
				padding: calc( #{$paddingTop} + .2em )  $paddingRight calc( #{$paddingBottom} - .2em) $paddingLeft;
		}
	}
}

// 呼び出し例
// .class {
//   padding: 20px 60px;
//   @include yu_lineHeight(20px , 60px , 20px , 60px);
// }

細かいところはここで説明しませんが、

_:-ms-lang(x)::-ms-backdrop , & { ・・・ }

この記述はIE11に対する「ブラウザハック」と呼ばれるテクニックです。当記事のテーマとは逸れる部分なので気になる方はググってください…。

途中で出てきている「#」はインターポレーションといって値を文字列として扱うことのできる機能です。

@at-rootはネストされてるスタイルセットをルートに戻す機能です。

/* コンパイル結果(style.css) */
.class {
  padding: 20px 60px;
}
_:-ms-lang(x)::-ms-backdrop, .class {
  padding: calc( 20px + .2em ) 60px calc( 20px - .2em) 60px;
}

コンパイルするとこんな感じになります。

z-indexの階層管理

カオスになりがちなz-indexを変数化し、上から並べることで直感的にわかりやすく管理します。

/* 変数設定 */
$layer: (
    modal : 1000,
    overlay : 100,
    hamburgerIcon : 30,
    header : 20,
    default : 1
);
/********************/

// mixin
@mixin z-index($key) {
	z-index: map-get($layer, $key);
}

// ※呼び出し例
// @include z-index(modal);

連想配列で任意の名前と値をペアにして変数にしている形をMap型といいます。Map型の変数を呼び出すにmap-getを使っています。

mixinの引数に値(key)を指定しているので、呼び出し時は変数の名前だけ記述すればOKです。

メディアクエリ

一番使用頻度が高いmixinです。

//ブレイクポイント変数設定
$mq-breakpoints: 
("xs": 320px, 
"sp": 480px, 
"tab": 600px, 
"pc" : 1025px, 
"full": 1100px);
/********************/

// スマホ基準(〜以上)
@mixin minmq($breakpoint: sp) {
	@media screen and (min-width: #{map-get($mq-breakpoints, $breakpoint)}) {
		@content;
	}
}

// PC基準(〜未満)
@mixin maxmq($breakpoint: sp) {
	@media screen and (max-width: #{map-get($mq-breakpoints, $breakpoint)}) {
		@content;
	}
}

// ※呼び出し例
// .class {
//  width: 50%;
//  @include maxmq(tab){
// 	 width: 100%;
// 	}
// }

ここでもMap型の変数とmap-get、値を文字列として読み込むための#(インターポレーション)を活用しています。

上のmixinでは初期値として引数にspを指定していますが、他の変数でももちろん大丈夫です。

まとめ

  • mixinはincludeとセットで使う
  • 引数を使うと値が柔軟に変化するmixinが作れる
  • 実務で使えるmixinを作るなら@ifや@contentなど他機能も抑えておきたい
  • @extend使う時はコンパイル後を予想して使いたい
  • とにかく便利!

mixinスニペットも解説が冗長になるのであえて簡単に書いている部分もあり、簡略しようと思えばまだまだできる部分はあります。

自分で使いながら検証してみて、よりスマートに書けるよう思考錯誤するとmixinやSassの理解も深まるかと思います!

当記事で書かれているmixinの範囲を抑えて、コーディング速度をアップさせましょう!

また、これを機にきちんとSassの知識を整理しておきたくなった方はこちらの記事も参考にしてみてください!