ボタンを100個作って分かった派生しやすい記述

webサイトには欠かせないボタン。
ページや用途によって様々な形のボタンを作りますよね。
同じカラーでも、形がちょっと違ったり、
文字の大きさだけ変えたいってこともあります。

ボタンの数が増えれば増えるほど、
コードが大混雑！なんてことになり兼ねません。

コードが混雑すると、
可視性が悪いのはもちろん、
後から修正するのも一苦労。
もう、そんなコードとはおさらばしよう！

今回派生しやすいボタン作りを検証するために、
「ボタンを100個作る」というタスクを追加しました。

ボタンを100!?
考えただけでもゾッとしますよね。笑

でも大丈夫！
派生しやすいボタンを作れば、
100個のボタンだってへっちゃらです！

まずは、完成したボタンを100個見てみましょう。

<img width="1081" alt="scss_button.png" src="https://qiita-image-store.s3.amazonaws.com/0/139029/ef61ce83-b49e-429d-2ec0-ac0b44c6573a.png">

ずらりと並ぶボタンは圧巻ですね！

今回ボタンを100個作って分かったことを
いくつかのポイントに分けてみます。

#ポイントその１：Sassを使う
今回派生しやすいボタン作りの記述に選んだのはSass。

Sassは「Syntactically Awesome Style Sheets」の略で、
簡単に訳すと「イケてるスタイルシート」ですが。笑

なぜSassを使うと派生しやすいのか？
ポイントは3つあります。
(Sassにはsassとscssの2つの記法がありますが、今回はscss記法を使っています。)

①変数が使える

```scss:scss
$white: #fff;

.c-btn {
  background: $white;
}
```

②ネストして書ける

```scss:scss
$white: #fff;

.c-btn {
  background: $white;
  &:hover {
    opacity: .7;
  }
}
```

③同じ値を何度も使える

```scss:scss
.c-btn {
  background: #fff;
  &:hover {
    opacity: .7;
  }
  &--white {
    @extend .c-btn;
    background: #000;
  }
  &--gray {
    @extend .c-btn;
    background: #666;
  }
}
```

Sassを使う利点は他にもたくさんありますが、
今回特にこの3つが大きなポイントになります。

#ポイントその2:@extendと@mixinをうまく使い分ける

Sassの中でも特に活用したのが、
@extendと@mixinの2つ。
どちらもスタイルの継承に使いますが、
ちょっとした違いがあります。
まずは2つの特徴を見てみましょう。

##@extend
@extendはスタイルの継承をしてくれるため、
同じスタイルを複数回使う際に活躍してくれます。

```scss:scss
.required {
  display: block;
  position: relative;
  box-sizing: border-box;
}

.c-btn {
  @extend .required;
  &:hover {
    opacity: .7;
  }
  &--white {
    @extend .c-btn;
    color: #fff;
  }
  &--gray {
    @extend .c-btn;
    color: #666;
  }
}
```

##@mixin
@mixinは@extendと同じようにスタイルを継承するのところまでは同じですが、
値の一部を変更する際に活躍してくれます。

```scss:scss
@mixin c-btn--triangle($color: #fff) {
  width: 100px;
  &:before {
    content: " ";
    display: block;
    border: 22px solid $color;
    border-top: 22px solid transparent;
    border-right: none;
    border-bottom: 22px solid transparent;
    position: absolute;
    top: 50%;
    right: -22px;
    transform: translateY(-50%);
  }
}
.c-btn--triangle {
  @include c-btn--triangle;
}
.c-btn--triangle-black {
  @include c-btn--triangle(#000);
}
```


さらに、大きく違う点は、
グルーピングされるか否か、という点です。

###@extendの場合

```scss:scss
.required {
  display: block;
  position: relative;
  box-sizing: border-box;
}

.c-btn {
  @extend .required;
  &:hover {
    opacity: .7;
  }
  &--white {
    @extend .c-btn;
    color: #fff;
  }
  &--gray {
    @extend .c-btn;
    color: #666;
  }
}
```

▼ コンパイル後

```css:css
.required, .c-btn, .c-btn--white, .c-btn--gray {
  display: block;
  position: relative;
  box-sizing: border-box; }

.c-btn:hover, .c-btn--white:hover, .c-btn--gray:hover {
  opacity: .7; }

.c-btn--white {
  color: #fff; }

.c-btn--gray {
  color: #666; }
```

###@mixinの場合

```scss:scss
@mixin c-btn--triangle($color: #fff) {
  width: 100px;
  &:before {
    content: " ";
    display: block;
    border: 22px solid $color;
    border-top: 22px solid transparent;
    border-right: none;
    border-bottom: 22px solid transparent;
    position: absolute;
    top: 50%;
    right: -22px;
    transform: translateY(-50%);
  }
}
.c-btn--triangle {
  @include c-btn--triangle;
}
.c-btn--triangle-black {
  @include c-btn--triangle(#000);
}
```

▼ コンパイル後

```css:css
.c-btn--triangle {
  width: 100px; }
  .c-btn--triangle:before {
    content: " ";
    display: block;
    border: 22px solid #fff;
    border-top: 22px solid transparent;
    border-right: none;
    border-bottom: 22px solid transparent;
    position: absolute;
    top: 50%;
    right: -22px;
    -webkit-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    transform: translateY(-50%); }

.c-btn--triangle-black {
  width: 100px; }
  .c-btn--triangle-black:before {
    content: " ";
    display: block;
    border: 22px solid #000;
    border-top: 22px solid transparent;
    border-right: none;
    border-bottom: 22px solid transparent;
    position: absolute;
    top: 50%;
    right: -22px;
    -webkit-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    transform: translateY(-50%); }
```

コンパイル後のグルーピングなので、
記述の際は特に気にかけることはないと思いますが、
cssだけで見てみると、
大きく違いが見えてくると思います。

例えば、
@extendは継承元のスタイルに関連性がある時に、
@mixinは、形が大きく異なる場合など、スタイルに関連性が少ない場合に、
というように、うまく使い分けていくと良いですね！

#ポイントその3：マルチクラスを使う

Sassを使えば派生しやすい記述ができる、
ということは分かりましたね。

しかし、100個のボタン全てにclass名を付けていくのはナンセンス！
いくつか元となるボタンが出来上がったら、
マルチクラスで対応するのが良いでしょう。

こうすることで、スタイルの記述は一気に削減できますね。

ただし、小さなスタイルごとに
classを追加するのも考えものです。
全てをマルチクラスで対応すると、
html上が混雑し、結果的に可視性の悪いコードとなってしまいます。

ある程度元になるスタイルをいくつか作り、
あとはスタイルの組み合わせて新しいスタイルを作るようにしていけば、
コードがスマートになるでしょう。

#まとめ
いかがでしたでしょうか？
いくつかのポイントを抑えれば、数十、数百単位のボタンでも、
派生しやすい記述ができるようになりますね！
<p data-height="265" data-theme-id="0" data-slug-hash="KoqZVV" data-default-tab="html,result" data-user="kfunnytokyo" data-embed-version="2" data-pen-title="scss button" class="codepen">See the Pen <a href="https://codepen.io/kfunnytokyo/pen/KoqZVV/">scss button</a> by kayukihashimoto (<a href="https://codepen.io/kfunnytokyo">@kfunnytokyo</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

おわり！