rakuishi.com

Sass の @mixin を使うと CSS ファイルに重複するコードが増えるなと思っていたけれど @extend を使うと解決した

@mixin は、Sass の便利な仕組みで関数のようなものです。試しに、タイトルの背景色だけが変わる @mixin を用意して以下のように使ってみます:

/* scss */
@mixin title-bg($color) {
  margin: 16px 0;
  padding: 1em;
  font-size: 16px;
  background-color: $color;
}

.title-bg-red {
  @include title-bg(red);
}

.title-bg-blue {
  @include title-bg(blue);
}

.title-bg-green {
  @include title-bg(green);
}

この SCSS をコンパイルすると以下のような CSS が生成されます:

/* css */
.title-bg-red {
  margin: 16px 0;
  padding: 1em;
  font-size: 16px;
  background-color: red;
}

.title-bg-blue {
  margin: 16px 0;
  padding: 1em;
  font-size: 16px;
  background-color: blue;
}

.title-bg-green {
  margin: 16px 0;
  padding: 1em;
  font-size: 16px;
  background-color: green;
}

このように @mixin を使うと似たようなコードをなんども記述しなくてよいのですが、上記の例では背景色を指定する background-color 部分以外のコードが重複し、CSS ファイルの容量が増えています。

これを @extend を使って書き直してます。@extend は、再利用されるセレクタを作成し、それを他のセレクタ内で展開して使います。継承という言葉がぴったりきます。以下のように書き直しました:

/* scss */
.title-bg {
  margin: 16px 0;
  padding: 1em;
  font-size: 16px;
}

.title-bg-red {
  @extend .title-bg;
  background-color: red;
}

.title-bg-blue {
  @extend .title-bg;
  background-color: blue;
}

.title-bg-green {
  @extend .title-bg;
  background-color: green;
}

この SCSS をコンパイルすると以下のような CSS が生成されます:

/* css */
.title-bg,
.title-bg-red,
.title-bg-blue,
.title-bg-green {
  margin: 16px 0;
  padding: 1em;
  font-size: 16px;
}

.title-bg-red {
  background-color: red;
}

.title-bg-blue {
  background-color: blue;
}

.title-bg-green {
  background-color: green;
}

@mixin を使った場合に比べて、コンパイル後の無駄な記述がなくなりました。

ただ、展開元となるセレクタが実際に CSS に出力される(それを意識した書き方・意味の持たせ方をする必要がある)、@extend する時に差異を持たせる部分(上記の例では、background-color)をその場で記述する必要があり、見通しが少し悪くなります。適材適所に使っていきたいです。