@ Sass

@mixin:ミックスイン

ミックスインの基本

ミックスインの機能を簡単に説明すると、スタイルの集まりを定義しておき、それをたの場所から呼び出して使うことができるというものです。また、引数を指定することで、定義したミックスインの値を一部変更して使うといった柔軟で強力な処理が可能です。

style.scss

@charset "utf-8";
// ミックスイン定義
@mixin boxSet {
  padding: 15px;
  background: #999;
  color: white;
}

ミックスインは、@mixin の後に半角スペースを空けて任意のミックスイン名を定義します。そして、{・・・} 内にスタイルを書いていきます。

定義したミックスインを呼び出す際は、「@include ミックスイン名」と書きます。

style.scss

@charset "utf-8";
// ミックスイン定義
@mixin boxSet {
  padding: 15px;
  background: #999;
  color: white;
}
// 定義したミックスインを呼び出し
.relatedArea {
  @include boxSet;
}
// 別のルールセットでも呼び出し
.pickupArea {
  @include boxSet;
}

コンパイル後の CSS は次のようになります。

style.css

.relatedArea {
  padding: 15px;
  background: #999;
  color: white;
}
.pickupArea {
  padding: 15px;
  background: #999;
  color: white;
}

引数を使ったミックスイン

引数は、ミックスインで定義した値の一部を変更する機能です。

引数を」使う場合は、ミックスイン名の直後に () を書き、() 内に引数(変数)を書きます。

style.scss

@charset "utf-8";
// 引数を使ったミックスイン定義
@mixin kadomaru($value) {
  -moz-border-radius: $value;
  -webkit-border-radius: $value;
  border-radius: $value;
}
.box {
  @include kadomaru(3px);
  background: #eee;
}
.item {
  border: 1px solid #999;
  @include kadomaru(5px 10px);
}

コンパイル後の CSS は次のようになります。

style.css

.box {
  -moz-border-radius: 3px;
  -webkit-border-radius: 3px;
  border-radius: 3px;
  background: #eee;
}
.item {
  border: 1px solid #999;
  -moz-border-radius: 5px 10px;
  -webkit-border-radius: 5px 10px;
  border-radius: 5px 10px;
}

引数に初期値を定義する

引数を使う際に、毎回値を定義するのは効率的ではありません、そこで、頻繁に使う値を引数の初期値として定義しておくと、初期値を変えたいときだけ値を書けば済むようになります。

style.scss

@charset "utf-8";
// 引数を使ったミックスイン定義
@mixin kadomaru($value: 3px) {
  -moz-border-radius: $value;
  -webkit-border-radius: $value;
  border-radius: $value;
}
.boxA {
  @include kadomaru; // 初期値を指定している場合は () を省略できます
  background: #eee;
}
.boxB {
  @include kadomaru();
  background: #f1f1f1;
}
.boxC {
  @include kadomaru(5px);
  background: #f1f1f1;
}

コンパイル後の CSS は次のようになります。

style.css

.boxA {
  -moz-border-radius: 3px;
  -webkit-border-radius: 3px;
  border-radius: 3px;
  background: #eee;
}
.boxB {
  -moz-border-radius: 3px;
  -webkit-border-radius: 3px;
  border-radius: 3px;
  background: #f1f1f1;
}
.boxC {
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
  background: #f1f1f1;
}

引数を複数指定する

引数は、,(カンマ)区切りで複数指定することも可能です。

style.scss

@charset "utf-8";
@mixin boxBase($margin: 30px 0, $padding: 10px) {
  margin: $margin;
  padding: $padding;
}
.boxA {
  @include boxBase;
  background: #eee;
}
.boxB {
  @include boxBase(0 0 50px, 20px);
  background: #f1f1f1;
}

.boxA では、ミックスインの引数をそのまま使い、.boxB では、複数の初期値を上書きしています。コンパイル後の CSS は次のようになります。

style.css

.boxA {
  margin: 30px 0;
  padding: 10px;
  background: #eee;
}

.boxB {
  margin: 0 0 50px;
  padding: 20px;
  background: #f1f1f1;
}

可変長引数を利用する

CSS のプロパティによっては、,(カンマ)を使うものがあります。たとえば text-shadow や box-shadow が該当します。これらを値としてそのまま使うとエラーになってしまいます。

下記のように、text-shadow の値を ,(カンマ)区切りで複数指定するとエラーになります。

このエラーの原因は、ミックスインには引数1つにつき1つの値しか渡すことができないためで、,(カンマ)区切りを使うと渡した引数が複数扱いになってしまうためエラーになってしまいます。

エラーを回避するには次のように文字列やリストとして引数を渡す必要があります。

style.scss

@charset "utf-8";
@mixin shadow($value) {
  text-shadow: $value;
}
// 複数の値を () で区切ってひとつのリストにする
h2 {
  @include shadow((8px 8px 0 #999, 15px -10px 0 #eee));
}
// 複数の値を "" や '' で囲って文字列にする
h2 {
  @include shadow(unquote("8px 8px 0 #999, 15px -10px 0 #eee")); // unquote() を使ってクォーテーションを削除する必要がある
}

そこで、次のように引数の後に「…」と記述する可変長引数を使います。

style.scss

@charset "utf-8";
@mixin shadow($value...) {
  text-shadow: $value;
}
h2 {
  @include shadow(8px 8px 0 #999, 15px -10px 0 #eee);
}

複数の引数があるミックスインを読み込む際に可変長引数を使う

可変長引数は、複数の引数があるミックスインを @inculde する際にも使うことができます。

style.scss

@mixin boxBase($w: 250px, $pd: 15px, $bg_c: #fff, $bd_c: #ccc) {
  width: $w;
  padding: $pd;
  background-color: $bg_c;
  border: 1px solid $bd_c;
}
$values: 300px, 20px;
.item {
  float: left;
  @include boxBase($values...);
}

変数「$values」に値が ,(カンマ)区切りで入っている場合に、可変長引数を使うことで、各値を別々の引数に渡すことができます。

コンパイル後の CSS は次のようになります。

style.css

.item {
  float: left;
  width: 300px;
  padding: 20px;
  background-color: #fff;
  border: 1px solid #ccc;
}

ミックスインのスコープ(利用できる範囲)を制限する

ミックスインもスコープを持つため、ルールセット内で書くとその中でしか利用できなくなります。

次のように、「.main」内で定義したミックスインは、「.main」内でしか使うことができません。

style.scss

@charset "utf-8";
.main {
  @mixin margin {
    margin: 50px 0;
  }
  .item {
    @include margin;
  }
}

以下の例では、エラーになってしまいます。

style.scss

@charset "utf-8";
.main {
  @mixin margin {
    margin: 50px 0;
  }

}
.item {
  @include margin;
}

ミックスインにコンテントブロックを渡す

ここまで解説したミックスインでは。@mixin でミックスインを定義して、定義したイックスインを「@include ミックスイン名;」と書いて呼び出していましたが、@content は、少し使い方がちがいます。

@content はルールセットやスタイルなどのコンテントブロックをミックスインンに渡す機能です。渡されたルールセットやスタイルは、@content が書かれた位置で展開されます。

例えば、IE7 の CSS ハックを使ってスタイルを追加したり上書きしたい場合、ネストを使って書くと次のようになります。

style.scss

@charset "utf-8";
.item {
  .image {
    float: left;
    *:first-child + html & {
      zoom: 1;
    }
  }
  .text {
    background: rgba(0,0,0,.2);
    *:first-child + html & {
      background: #eee;
    }
  }
}

このように、IE7 のハックを何度も書くのは面倒ですし、ハックなのか単純にスタイルを適用したいのか区別しにくくなっています。

こういった場合に @content を使うと記述量が減り、可読性の高いソースコードにすることができます。

style.scss

@charset "utf-8";
@mixin hackIE7 {
  *:first-child + html & {
    @content;
  }
}

.item {
  .image {
    float: left;
    @include hackIE7 {
      zoom: 1;
    }
  }
  .text {
    background: #rgba(0,0,0,.2);
    @include hackIE7 {
      background: #eee;
    }
  }
}

あらかじめ @mixin で IE7 用のハックを定義しておき、使いたい位置で @include を使って呼び出し {・・・}内に IE7 用のスタイルを書きます。

コンパイル後の CSS は次のようになります。

style.css

.item .image {
  float: left;
}
*:first-child + html .item .image {
  zoom: 1;
}
.item .text {
  background: #rgba 0, 0, 0, 0.2;
}
*:first-child + html .item .text {
  background: #eee;
}

ミックスイン名で使える文字と使えない文字

ミックスイン名の命名規則は変数名と同じで、英数字の他に、_(アンダースコア)、-(ハイフン)を使うことができます。また、マルチバイト文字も使えるので日本語でも大丈夫です。

変数名に使える文字の例

@mixin shadow1 {・・・}
@mixin shadow-1 {・・・}
@mixin w_1 {・・・}
@mixin 影 {・・・}
@mixin shadow {・・・}
@mixin _shadow1 {・・・}
@mixin -shadow1 {・・・}

変数名に使えない文字の例

@mixin 01shadow1 {・・・} //数字から始まっている
@mixin shadow@2 {・・・} //@など使えない文字から始まっている
@mixin --shadow1 {・・・} //連続したハイフンから始まっている