【コンポーネント】ボタンがしんどいので汎用的なボタンを作ってみた

Webサイトに「必ずある」と言っても過言ではない要素…

おぉ…ボタンよ…

昔は[スキューモーフィズム](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%AD%E3%83%A5%E3%83%BC%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0)なデザインのボタンを画像で配置していましたよね。
[Web2.0なデザインのボタン](https://www.google.com/search?q=web2.0+button&tbm=isch&ved=2ahUKEwixxu62i-PsAhVThMYKHdM0BqwQ2-cCegQIABAA&oq=web2.0+button&gs_lcp=CgNpbWcQA1DcRFjJSmC5TGgAcAB4AIABswGIAbgEkgEDNS4xmAEAoAEBqgELZ3dzLXdpei1pbWfAAQE&sclient=img&ei=65OfX_GkPNOImgbT6ZjgCg&bih=988&biw=1781&rlz=1C1QABZ_jaJP915JP915)が懐かしい…

[フラットデザイン](https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%A9%E3%83%83%E3%83%88%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3)が主流の今ではCSSでの装飾が当たり前となりました。

一見、実装が簡単そうに見えるボタンですが、実は奥が深いんですよ…

こんな経験ありませんか？

* ボタンの大きさのバリエーションが多い…:sob:
* ボタンの色のバリエーションが多い…:dizzy_face:
* アイコンの位置がバラバラ…:weary:
* アイコンが2つ配置…:cry:
* アイコンの種類が多い…:sweat:
* アイコンの大きさがバラバラ…:persevere:

というわけで、このような場面にも簡単に対応できる汎用的なボタンを作ってみようと思います！

## 仕様

以下項目が設定可能なボタンを作成する。
アイコンについてはアイコンフォントを利用します。

* タグ
  * a
  * button
* 横幅
  * デフォルト幅（min-width）
  * ラベルの幅
  * 親要素の幅100%
* 高さ
  * デフォルトの高さ（min-height）
  * 小さいボタン
  * 大きいボタン
* アイコンの位置
  * 左端
  * ラベルの左
  * ラベルの右
  * 右端
* アイコンの数
  * 左端 or ラベルの左に1つ
  * 右端 or ラベルの右に1つ
* アイコンの種類と大きさ
  * CSSに記述することで設定可能

## 実装

HTMLのマークアップは以下となります。
ボタンの設定項目についてはdata属性を利用します。

```html:index.html
<a class="btn" href="">ボタン</a>
<button class="btn" type="button">ボタン</button>
```

ボタンのベースとなるSassは以下となります。

* Sassの変数で以下を管理
  * ボタンの最小幅
  * ボタンの最大幅
  * ボタンの最小の高さ
* アイコンについてはFont Awesomeを利用

https://fontawesome.com/icons

```scss:btn.scss
$btn-min-width: 250px;
$btn-max-width: 400px;
$btn-min-hight: 50px;
.btn {
  display: inline-grid;
  grid-template-columns: 1fr auto 1fr;
  column-gap: 0.5em;
  align-items: center;
  justify-content: center;
  min-width: $btn-min-width;
  min-height: $btn-min-hight;
  padding: 10px 1.5em;
  font-weight: 700;
  color: #fff;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  background-color: #ca5673;
  border: 0;
  border-radius: 20px;
  outline: none;
  transition: background-color 0.2s ease-out;
  &:visited,
  &:active {
    color: #fff;
  }
  &:hover {
    background-color: #a7475f;
  }
  @media (max-width: 559px) {
    width: 100%;
    min-width: auto;
    max-width: $btn-max-width;
  }
}
```

### 横幅

横幅の設定は `data-btn-width` 属性に以下の値を設定します。
ただし、スマホ時には全て同じ幅になります。

* data-btn-width="**auto**"
* data-btn-width="**fluid**"

```html:index.html
<!-- デフォルト幅 -->
<a class="btn" href="">ボタン</a>
<!-- ボタンのラベルの幅 -->
<a class="btn" href="" data-btn-width="auto">ボタン</a>
<!-- 親要素の幅100% -->
<a class="btn" href="" data-btn-width="fluid">ボタン</a>
```

```scss:btn.scss
.btn {
  // ボタンのラベルの幅
  &[data-btn-width="auto"] {
    min-width: auto;
  }
  // 親要素の幅100%
  &[data-btn-width="fluid"] {
    min-width: 100%;
  }
}
```

### 高さ

高さの設定は `data-btn-height` 属性に以下の値を設定します。
大きさのバリエーションがもっと欲しい場合は `data-btn-height` 属性の値を増やすことで対応可能です。

* data-btn-height="**small**"
* data-btn-height="**large**"

```html
<!-- デフォルトの高さ -->
<a class="btn" href="">ボタン</a>
<!-- 小さいボタン -->
<a class="btn" href="" data-btn-height="small">ボタン</a>
<!-- 大きいボタン -->
<a class="btn" href="" data-btn-height="large">ボタン</a>
```

```scss:btn.scss
$btn-min-hight-small: 40px;
$btn-min-hight-large: 60px;
.btn {
  // 小さいボタン
  &[data-btn-height="small"] {
    min-height: $btn-min-hight-small;
  }
  // 大きいボタン
  &[data-btn-height="large"] {
    min-height: $btn-min-hight-large;
  }
}
```

### アイコンの位置

アイコンの位置は `data-btn-icon-` の後に位置を指定したdata属性名で指定します。
data属性値で指定しないので注意してください。

* data-btn-icon-**left**="angle-right"
* data-btn-icon-**before**="angle-right"
* data-btn-icon-**after**="angle-right"
* data-btn-icon-**right**="angle-right"

```html
<!-- 左端 -->
<a class="btn" href="" data-btn-icon-left="angle-right">ボタン</a>
<!-- ラベルの左 -->
<a class="btn" href="" data-btn-icon-before="angle-right">ボタン</a>
<!-- ラベルの右 -->
<a class="btn" href="" data-btn-icon-after="angle-right">ボタン</a>
<!-- 右端 -->
<a class="btn" href="" data-btn-icon-right="angle-right">ボタン</a>
```

```scss:btn.scss
.btn {
  // アイコンフォントを設定
  &::before,
  &::after {
    content: "";
    font-family: "Font Awesome 5 Free";
  }

  // アイコンの位置を設定
  &[data-btn-icon-left]::before,
  &[data-btn-icon-after]::after {
    justify-self: start;
  }
  &[data-btn-icon-before]::before,
  &[data-btn-icon-right]::after {
    justify-self: end;
  }
}
```

### アイコンの種類

アイコンの種類は `data-btn-icon-xxxx` 属性の値で設定します。

* data-btn-icon-before="**angle-right**"

```html
<!-- 右矢印アイコン -->
<a class="btn" href="" data-btn-icon-before="angle-right">ボタン</a>
```

以下は全ての位置（左端、ラベルの左、ラベルの右、右端）に表示させるように記述していますが、必要な位置だけ記述してください。

```scss:btn.scss
.btn {
  // 右矢印アイコン
  &[data-btn-icon-left="angle-right"]::before,
  &[data-btn-icon-before="angle-right"]::before,
  &[data-btn-icon-after="angle-right"]::after,
  &[data-btn-icon-right="angle-right"]::after {
    font-size: 1.2em;
    content: "\f105";
  }
}
```

## デモ
<p class="codepen" data-height="500" data-theme-id="light" data-default-tab="css,result" data-user="taqumo" data-slug-hash="qBNrmME" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Button">
  <span>See the Pen <a href="https://codepen.io/taqumo/pen/qBNrmME">
  Button</a> by Takuya Mori (<a href="https://codepen.io/taqumo">@taqumo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>