色が可変のチェックボックスを作った話

チェックボックスについて詳しくなれたので初投稿です。

今回このようなチェックボックスを作成してみました。
![checkbox.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/52211d24-533b-6883-8bef-9146f65e3c92.gif)
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JjLNEoM" data-user="fujita234" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/fujita234/pen/JjLNEoM">
  色可変のCheckbox</a> by tksn07 (<a href="https://codepen.io/fujita234">@fujita234</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 早くコードをコピペしたい人はこちら

https://codepen.io/fujita234/pen/JjLNEoM

# どうやって作ったかの説明

突然ですが皆さん。
どのようなチェックボックスを作成したことありますか？
チェックボックスを作成する方法は色々あると思います。

- デフォルトのチェックボックスを使う
- チェックボックスのアイコンを使う
- チェックボックスの画像を使う
- 頑張って作る

様々な作り方がある中。今回私は「頑張って作る」を採用しました。

## なぜ「頑張って作る」を採用したか
「チェックボックスを作ってほしい！」という依頼が突然、私に来ました。
「どんなチェックボックス？」と聞いたところ
「googleカレンダーみたいなチェックボックス！」という話でした。
「ほうほう...googleカレンダーみたいなチェックボックス...」
確認してみるとこんなチェックボックスでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/29919b19-2518-7870-4415-cb4e844cc916.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/2b8d4bac-afe0-aaa5-62c2-075754d75449.png)
この時点で「デフォのチェックボックスじゃだめだな...」と思います。
そしてその色が可変ときたじゃありませんか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/48f0f1fd-100f-9217-0337-4c84c0597284.png)

この色が可変というのがなかなか厄介で
この段階で、
- デフォルトのチェックボックスを使う
    - A. デフォじゃこんなの作れない
- チェックボックスのアイコンを使う
    - A. アイコンに色付けもチェックだけ白なんて無理
    - もしかしたらこれでもいける...?
- チェックボックスの画像を使う
    - A. 色の度に画像つくる？無理

ってことで「頑張って作る。」を採用しました。

## どうやって作ったか？
上で紹介した。コードをコピペしたい人向けのコードを説明していきたいと思います。
まずhtmlはこのような構造になっています。

```html
<div class="container">
  <label class="control control--checkbox">
    <div class="control-group">
      <input type="checkbox" checked="checked"/>
      <div class="control__indicator"></div>
      <div class="text-name">First checkbox</div>
    </div>
  </label>
</div>
```

まだcssは適用させてません。
この段階で、画面はこのようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/4bb89deb-1350-8dbe-1a0e-82bd6f066390.png)

まだまだ見た目通りじゃありません。
これに一個ずつcssを適用させていきましょう。
```css
/* デフォのcheckboxを消す */
input[type="checkbox"] {
  display: none;
}
```
まずはデフォルトで表示されているチェックボックスを非表示にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/5598ec30-0d21-eed7-3b22-cd87acd3e8a0.png)
これでチェックボックスが消えました。
では、代わりのスタイルを適用させたチェックボックスを作成していきましょう。

```css
/* チェックボックス checked=false */
.control__indicator {
  height: 20px;
  width: 20px;
  background: white;
  border-radius: 5px;
  border: solid blue;
}
```
このcssがチェックボックスがfalseの時に表示されるチェックボックスになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/006903de-9610-1f62-c313-b7acff5278f5.png)
`height`と`width` がチェックボックスの大きさを表現してます。

```css
/* チェックボックス checked=true */
.control input:checked + .control__indicator {
   background: blue;
}
```
次にこのcssを適用させることで、チェックボックスがtrueの時、色が変わるのを表現させています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/e2f36630-6de6-b8c6-7fcd-ade923593ae7.png)
クリックし、checked=trueになると、`background: blue;`が適用され、真っ青になるという仕組みです。

また、+ マークは、隣接している要素に適用という力があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/d61b666a-eb58-9973-b680-00d5f93c5152.png)

次にチェックマークです。
チェックマークはこのようなcssになっています。
```css
.control__indicator::before {
  content: '';
  display: block;
  position: relative;
  left: 8px;
  top: 4px;
  width: 3px;
  height: 8px;
  border: solid blue;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 1;
}
```
borderで頑張ってチェックマークっぽいのを作って、それを45°回転させて表現しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/89d16137-0c7e-c178-e94e-82952465cd0e.png)

また、before要素を使ってます。beforeに関してはこちらの記事がわかりやすかったので載せておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/ee74c319-4e42-3485-f9a7-65397f54f939.png)

これで、チェックボックスの上にチェックを配置。というやり方を取っています。

そして、次に、チェックがtrueの時のチェックマークも作成していきましょう。
```css
/* チェックマーク checked=true */
.control__indicator::after {
  content: '';
  display: block;
  position: relative;
  left: 8px;
  top: -6px;
  width: 3px;
  height: 8px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 1;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/0daae921-cf6e-5cc7-b479-f645c1754ae8.png)

これでチェックがtrueのチェックマークを表現出来ました。
しかし、チェックがfalseだと、このような画面になってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/23881b73-62e7-62c0-9126-8f72e1912737.png)

なので、
- チェックがtrueなら、白のチェックマークを表示、
- チェックがfalseなら、青のチェックマークを表示
を実現させなければいけません。

それを実現させるのがこちら

```css
/* チェックマークを表示させる */
.control input:checked + .control__indicator::after {
  opacity: 1;
}
/* チェックマークを表示させる checked=false */
.control input:not(:checked) + .control__indicator::before {
  opacity: 1;
}
```
opacityとは不透明度を表現するcssです。
なお、このタイミングで、チェックマークの opacityを0に修正してください。

```css
/* チェックマーク checked=false */
.control__indicator::before {
  content: '';
  display: block;
  position: relative;
  left: 8px;
  top: 4px;
  width: 3px;
  height: 8px;
  border: solid blue;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 0; /* ここ変えたよ！ */
}

/* チェックマーク checked=true */
.control__indicator::after {
  content: '';
  display: block;
  position: relative;
  left: 8px;
  top: -6px;
  width: 3px;
  height: 8px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 0; /* ここ変えたよ！ */
}
```

これで不透明度をいじくることで、チェックマークを変える。というのを表現しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/e9760e10-eb30-0ae0-e662-2fa5c63dfca4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/94d30d0d-ecb1-118f-a22e-8663106a46c1.png)

これでいい感じになりました。
後は、いい感じにそろえて、
```css
.control-group {
  display: flex;
  position: relative;
  padding: 5px;
  box-sizing: border-box;
  align-items: center;
}

/* textのスタイル */
.text-name {
  padding-left: 8px;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/541b6b7e-a1af-7ea9-e50d-8d8b7383aa73.png)

完成です！
後は、色を変数で渡したり、
Reactならこのチェックボックスをコンポーネントで切って使いまわすなどできます。
是非「googleカレンダーみたいなチェックボックス作って！」
という要望が来た時に参考してください。

では ノシ

# 参考サイト
- [意外と知らない!?CSSセレクタ20個のおさらい](http://weboook.blog22.fc2.com/blog-entry-268.html)
- [チェックボックスをおしゃれにするCSSスニペット25選。アニメーションが刺さる！](https://kodocode.net/design-css-checkbox/)
- [擬似要素タグbeforeとafterを活用しよう！基礎知識と使い方を解説！](https://www.asobou.co.jp/blog/web/before-after)
- [opacity](https://developer.mozilla.org/ja/docs/Web/CSS/opacity)