🌟

Sassの汎用的なmixinの作り方

2021/10/25に公開

Sassでは、引数を用いることでより汎用的なmixinを作成することができます。
今回は実例をご紹介しつつ、汎用的なmixinの作り方について解説します。

今回使用する例

今回はこちらの記事の内容を元に汎用的なmixinを作成してみます。
https://www.nxworld.net/css-multiline-animation.html

何度も同じCSSを書くのは大変で非効率なので、どこでも使えて、スタイル(ボーダーの幅や色など)のバリエーションを自由に指定できる汎用的なmixinを作成することを目指します。

ソースコード

まず、mixinはこのように定義します。

@mixin hover_underline($target: "span", $padding: 0, $borderColor: #000, $borderWidth: 1px, $duration: 0.4s) {
  #{$target} {
    padding-bottom: $padding;
    background-image: linear-gradient($borderColor, $borderColor);
    background-position: left bottom;
    background-size: 0 $borderWidth;
    background-repeat: no-repeat;
    transition: background $duration ease-out;
  }
  &:hover {
    #{$target} {
      background-size: 100% $borderWidth;
    }
  }
}

mixinを呼び出すときはこのように記述します。

@include hover_underline(".selector", 0, #ccc, 4px, 0.3s);

では早速、上記のソースコードの解説に移ります。

各引数の概要

上記の例では、$target$padding$borderColor$borderWidth$durationの5つの引数が用意されています。

引数 説明
$target アニメーションを指定したい対象を指定する
$padding ボーダーを表示する上下位置を指定する
$borderColor ボーダーの色を指定する
$borderWidth ボーダーの幅を指定する
$duration アニメーションが完了するまでの所要時間(transition-duration)を指定する

引数のデフォルト値

Sassのmixinやfunctionなどでは、$hoge: デフォルト値の形で、引数のデフォルト値を指定することができます。mixinを呼び出す際に特に引数値を指定しなければ、デフォルト値が採用されます。

以下の例は@include hover_underline("span", 0, #000, 1px, 0.4s);と同義です。

@include hover_underline;

また、mixinを呼び出す際に引数値を指定すると、指定した引数値が採用されます。

@include hover_underline(".selector", 0, #ccc, 4px, 0.3s);

上記の例では、mixinを呼び出す際にすべての引数を指定しましたが、引数名を明示することで特定の引数値のみを指定することも可能です。

以下の例は@include hover_underline(".selector", 0, #000, 1px, 0.3s);と同義です。

@include hover_underline($target: ".selector", $duration: 0.3s);

セレクタに引数値を使用する

Sassでは#{$selector} {}の形で、functionやmixinの引数をセレクタに使用することができます。

@mixin hover_underline($target: "span") {
  #{$target} {}
}

今回の例では、セレクタを引数で指定することで、アニメーションを付与したい対象が要素セレクタでもclassセレクタでも柔軟に対応できるようになりました。

おまけ

ソースコードの解説は以上ですが、最後に今回の例を実際に使用した際のソースコードを置いておきます。引数のデフォルト値にSCSS変数が指定されたり、Dart Sassの名前空間が指定されたりと、やや複雑になっていますが、よかったら参考にしてみてください。

// 定義
@mixin hover_underline($target: "span", $padding: 0, $borderColor: variables.$color_black, $borderWidth: 1px, $duration: 0.4s) {
  @include breakpoint.md {
    #{$target} {
      padding-bottom: $padding;
      background-image: linear-gradient($borderColor, $borderColor);
      background-position: left bottom;
      background-size: 0 $borderWidth;
      background-repeat: no-repeat;
      transition: background $duration variables.$ease_out_quint;
    }
  }
  @include hover {
    #{$target} {
      background-size: 100% $borderWidth;
    }
  }
}

// 使用
.parent {
  @include global.hover_underline(".selector", 2px, global.$color_primary, 4px, 0.3s);
}
GitHubで編集を提案

Discussion