CSSは簡単に記述することができ、学習コストが低いのが特徴です。
一方で繰り返しに弱く、コードが冗長になりがちだというデメリットも存在します。

そこでSassをはじめとして、関数や変数の処理を行うことができるプリプロセッサー言語を使う現場が増えています。
できるだけコンパクトにコードを書こうという動きも一般的になりつつあります。

Sassの中でもとりわけ便利な機能が、mixinと呼ばれる機能です。
mixinはSassにおける関数のようなもので、値を渡してスタイルなどを返します。

「@mixin」の後ろに名前をつけ、任意で引数を使う場合は「$」の後に名前をつけます。
呼び出す際には「@include」の後にmixin名をつけて呼び出します。

今回は、今日から実践的に使えるSassの便利なmixinをご紹介します。
よく使うものはスニペットにして保存しておき、いつでも再利用できるようにしておくと便利です。

参考:
[今からでも遅くない!基礎から学ぶSass入門]

今日からSassで使える便利なmixin

1. 上下左右中央配置

天地と左右に中央配置するときに、みなさんならどのようなコードを書くでしょうか。
一瞬考えて思い出そうとしますが、mixinとして登録しておけば短いコードですぐに記述することができます。

@mixin center {
  text-align: center;
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  transform: translateY(-50%);
}

2. リンクカラーの生成

場所によってリンクの色を変えたいときはありませんか。
その場合、hoverやactive、focusなどの色まで一つひとつ指定するのは面倒です。
次のmixinでは、指定した色でリンクカラーを生成し、hoverなどの色は20%明るい色を使うことで一気にリンクカラーのセットを作成することができます。

@mixin link-color($color) {
  color: $color;

  &:hover, &:active, &:focus {
    color: lighten($color, 20%);
  }
}

3. 透明度の指定

透明度といえばopacityの設定ですが、IEも含めたクロスブラウザ対応のopacityの設定をmixinで表現してみました。

@mixin opacity($opacity) {
  opacity: $opacity;
  $ieopacity: ($opacity * 100);
  filter: alpha(opacity=$ieopacity);
}

4. フォントサイズの指定 (rem対応)

CSS3で登場した新しい単位remでフォントサイズを指定します。
emや%などの相対指定、pxやptなどの絶対指定などが一般的ですが、remは親要素の影響を受けずにフォントサイズを指定することができるので便利です。

@mixin font-size($size, $base: 16) {
  font-size: $size + px;
  font-size: ($size / $base) + rem;
}

5. 三角矢印

上下左右にCSSだけで表現できる矢印を作成できるmixinです。
borderで表現しているので、なかに文字を入れることはできません。
なお、すべて省略すると、右向きの高さ12pxのグレーの矢印になります。

@mixin trianglearrow($direction: right, $size: 12, $color: $gray){
  $set: left;

  @if $direction == left{
    $set: right;
  }@elseif $direction == top{
    $set: bottom;
  }@elseif $direction == bottom{
    $set: top;
  }@else{
    $set: left;
  }
  $size: round($size / 2);
 
  width: 0;
  height: 0;
  border: $size + px solid transparent;
  border-#{$set}-color: $color;
}

6. 矢印

次に棒付きの矢印を表現してみましょう。
サイズ、線の太さ、線の種類、色、矢印の向きを指定することができます。
方向によってtransformの計算方法が異なるので、若干長くなっています。

@mixin arrow($size, $border-width, $border-style, $border-color, $direction) {
  content: "";
  display: inline-block;
  position: absolute;
  top: 50%;
  width: $size;
  height: $size;
  margin-top: - ($size / 2);
  border: $border-width $border-style $border-color;
  @if $direction == up {
    -webkit-transform: rotate(-135) + deg;
     -moz-transform: rotate(-135) + deg;
    transform: rotate(-135) + deg;
  }
  @else if $direction == under {
    -webkit-transform: rotate(45) + deg;
    -moz-transform: rotate(45) + deg;
    transform: rotate(45) + deg;
  }
  @else if $direction == right {
    -webkit-transform: rotate(-45) + deg;
    -moz-transform: rotate(-45) + deg;
    transform: rotate(-45) + deg;
  }
  @else if $direction == left {
    -webkit-transform: rotate(135) + deg;
    -moz-transform: rotate(135) + deg;
    transform: rotate(135) + deg;
  }
  @else {
    -webkit-transform: rotate($direction) + deg;
    -moz-transform: rotate($direction) + deg;
    transform: rotate($direction) + deg;
  }
}

7. モダンなグラデーション背景

最近では同系の2色を指定してモダンで洗練されたような色のグラデーションを使った背景を実装しているホームページも増えてきました。
なかなか色の組み合わせが思いつかないという場合、使いたい色を1色指定すると、もう1色は自動的に指定してくれます。

@mixin bg-gradient($angle: 180deg, $color: #0bd, $amount: 20%) {
  background: linear-gradient($angle, $color, adjust-hue($color, $amount)) fixed;
}

8. 文字にグラデーション

先ほど背景にグラデーションを適用する方法を紹介しましたが、文字色としてグラデーションを扱うにはどうすればいいでしょうか。
下記のmixinでは、background-clipで文字部分だけグラデーションを切り抜き、対応していないブラウザでは指定した1色を表示するようにしています。

@mixin gradient-text($angle: 45deg, $color: #f82, $amount: 35%) {
  color: $color;
  background: -webkit-linear-gradient($angle, $color, adjust-hue($color, $amount));
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  display: inline-block;
}

9. 自動でベンダープレフィックスをつける

CSS3を使うとき、必ずと言っていいほどベンダープレフィックスを使うようになるでしょう。
下記のmixinを使うことで、毎回つけていたベンダープレフィックスの付与を自動化することができます。

@mixin prefixes($property, $value) {
  @each $prefix in -webkit-, -moz-, -ms-, -o-, '' {
    #{$prefix}#{$property}: $value;
  }
}

10. メディアクエリをmixinでまとめる

セレクタごとにメディアクエリを指定するのは面倒なので、mixinでまとめて@contentで要素のコンテンツを引き継ぐと楽になります。

@mixin mediaquery($breakpoint: 768px) {
  @media screen and (min-width: $breakpoint) {
    @content;
  }
}

11. 長文テキストを枠内に収める

最後に、長文テキストをはみ出さないように枠内に収めるためのmixinを紹介します。

@mixin truncate($width: 100%) {
  width: $width;
  max-width: 100%;
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}