コンテンツにスキップ
トップに戻る

ミックスイン

ミックスインと関数は同じように定義されますが、適用方法が異なります。

例えば、以下のように定義された `border-radius(n)` という関数があり、これは *ミックスイン* として呼び出されます (つまり、式の一部ではなく、文として呼び出されます)。

`border-radius()` がセレクター内で呼び出されると、プロパティが展開され、セレクターにコピーされます。

border-radius(n)
  -webkit-border-radius n
  -moz-border-radius n
  border-radius n

form input[type=button]
  border-radius(5px)
border-radius(n)
  -webkit-border-radius n
  -moz-border-radius n
  border-radius n

form input[type=button]
  border-radius(5px)

コンパイル結果

form input[type=button] {
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}
form input[type=button] {
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}

ミックスインを使用する場合、括弧を完全に省略でき、優れた透過的なベンダープロパティのサポートを提供します!

border-radius(n)
  -webkit-border-radius n
  -moz-border-radius n
  border-radius n

form input[type=button]
  border-radius 5px
border-radius(n)
  -webkit-border-radius n
  -moz-border-radius n
  border-radius n

form input[type=button]
  border-radius 5px

ミックスイン内の `border-radius` は、再帰的な関数呼び出しではなく、プロパティとして扱われることに注意してください。

これをさらに進めるために、渡された式を含む自動的な `arguments` ローカル変数を利用して、複数の値を渡すことができます

border-radius()
  -webkit-border-radius arguments
  -moz-border-radius arguments
  border-radius arguments
border-radius()
  -webkit-border-radius arguments
  -moz-border-radius arguments
  border-radius arguments

これで、`border-radius 1px 2px / 3px 4px` のように値を渡すことができます!

また、インターポレーション ` {param}`を利用することもできます

border(side, args...)
  if side
    border-{side}  args
  else
    border args

.border-thick
  border('left' , 10px, 'darkred')

.border
  border('' , 1px, 'darkred')
border(side, args...)
  if side
    border-{side}  args
  else
    border args

.border-thick
  border('left' , 10px, 'darkred')

.border
  border('' , 1px, 'darkred')

レンダリング結果

.border-thick {
  border-left: 10px 'darkred';
}
.border {
  border: 1px 'darkred';
}
.border-thick {
  border-left: 10px 'darkred';
}
.border {
  border: 1px 'darkred';
}

この優れた用途のもう1つは、IEの `opacity` サポートなど、ベンダー固有の透過的なサポートの追加です。

support-for-ie ?= true

opacity(n)
  opacity n
  if support-for-ie
    filter unquote('progid:DXImageTransform.Microsoft.Alpha(Opacity=' + round(n * 100) + ')')

#logo
  &:hover
    opacity 0.5
support-for-ie ?= true

opacity(n)
  opacity n
  if support-for-ie
    filter unquote('progid:DXImageTransform.Microsoft.Alpha(Opacity=' + round(n * 100) + ')')

#logo
  &:hover
    opacity 0.5

レンダリング結果

#logo:hover {
  opacity: 0.5;
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
}
#logo:hover {
  opacity: 0.5;
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
}

親参照

ミックスインは、親参照文字 `&` を利用して、さらにネストする代わりに親に対して作用できます。

たとえば、テーブル行をストライプにするための `stripe(even, odd)` ミックスインを作成したいとします。`even` と `odd` の両方にデフォルトの色の値を指定し、行に `background-color` プロパティを割り当てます。`tr` の内部にネストされた `&` を使用して、`tr` を参照し、`even` カラーを提供します。

stripe(even = #fff, odd = #eee)
  tr
    background-color odd
    &.even
    &:nth-child(even)
      background-color even
stripe(even = #fff, odd = #eee)
  tr
    background-color odd
    &.even
    &:nth-child(even)
      background-color even

次に、以下に示すようにミックスインを利用できます

table
  stripe()
  td
    padding 4px 10px

table#users
  stripe(#303030, #494848)
  td
    color white
table
  stripe()
  td
    padding 4px 10px

table#users
  stripe(#303030, #494848)
  td
    color white

あるいは、`stripe()` は親参照なしで定義できます

stripe(even = #fff, odd = #eee)
  tr
    background-color odd
  tr.even
  tr:nth-child(even)
    background-color even
stripe(even = #fff, odd = #eee)
  tr
    background-color odd
  tr.even
  tr:nth-child(even)
    background-color even

必要に応じて、`stripe()` をプロパティであるかのように呼び出すことができます

stripe #fff #000
stripe #fff #000

ブロックミックスイン

ミックスインにブロックを渡すには、`+` プレフィックス付きでミックスインを呼び出します

+foo()
  width: 10px
+foo()
  width: 10px

渡されたブロックは、ミックスイン内で `block` 変数として使用でき、インターポレーションで使用できます

foo()
  .bar
    {block}

+foo()
  width: 10px

=> .bar {
      width: 10px;
    }
foo()
  .bar
    {block}

+foo()
  width: 10px

=> .bar {
      width: 10px;
    }

この機能は、現在まだ粗い状態ですが、将来的には強化される予定です。

ミックスイン内でのミックスインの混合

ミックスインは、(当然!)他のミックスインを利用して、独自のセレクターとプロパティを構築できます。

たとえば、以下では、順序なしリストをインライン化(`inline-list()` 経由)し、カンマ区切りにするために、`comma-list()` を作成します。

inline-list()
  li
    display inline

comma-list()
  inline-list()
  li
    &:after
      content ', '
    &:last-child:after
      content ''

ul
  comma-list()
inline-list()
  li
    display inline

comma-list()
  inline-list()
  li
    &:after
      content ', '
    &:last-child:after
      content ''

ul
  comma-list()

レンダリング結果

ul li:after {
  content: ", ";
}
ul li:last-child:after {
  content: "";
}
ul li {
  display: inline;
}
ul li:after {
  content: ", ";
}
ul li:last-child:after {
  content: "";
}
ul li {
  display: inline;
}