display: noneを使ってCheckboxを実装するのはやめようね。

# TL:DR
カスタムチェックボックス(Custom Checkbox)を作成する際は、`display: none`, `visible: none` を使わずに、`appearance: none` か `opacity: 0` で実装しよう！

# 本文

こんにちは。[最近ChatGPTを使ってフィーちゃんと共に暮らしているTaka](https://note.com/67512/n/n097f3aa47dab)です!

今回は、前回自分が作ったチェックボックスを駄目だしする記事になります。
まず私は前回このような記事を書きました

https://qiita.com/Tksn07/items/6496890e22a6332949e5

そしてそれによって出来たチェックボックスはこちらです。

<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>


こちらのCheckbox。ある観点が抜け落ちて実装されていました。
それが、 **アクセシビリティ** です。

近年、[障害者差別解消法の改正](https://www8.cao.go.jp/shougai/suishin/sabekai.html)　により、アクセシビリティの需要が高まってきています。
それにより、取り組み自体は必ずしも絶対ではないですが、実装する段階である程度は担保した実装をしておくと良い。という流れになってきています。

その流れから自分が改めてアクセシビリティの観点で振り返ってみた所、前回書いた記事が見事にNGを踏んでいたので、この記事を元に

・**何がアクセシビリティの観点でNGだったのか？**
・**どういった実装がOKと言えるのか？** 

について語っていこうと思います。


## カスタムチェックボックスに `display: none` はダメ絶対！

まず前回の記事でNGを踏んでしまっていたのが、 `display: none` です。

なぜダメなのか？
それは、`display: none`は、スクリーンリーダーに読み取ってもらえなく、アクセシビリティが下がるからです。

↓参照

https://developer.mozilla.org/ja/docs/Web/CSS/display#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B7%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3%E3%81%AE%E8%80%83%E6%85%AE

`display: none`
> 要素の display の値に none を使用すると、その要素はアクセシビリティツリーから削除されます。すなわち、その要素とすべての子孫要素は読み上げ技術によって読み上げられなくなります。

カスタムチェックボックスの作り方でググると、ほとんどの記事で `display: none` を使って実装しています。(私含め)
しかし、それはアクセシビリティの観点を踏まえるとあまり良いと言える実装ではないでしょう。

では一体どんな実装方法があるのでしょうか？

## 彡(ﾟ)(ﾟ)｢せや！んじゃ `visibility: none` で消して実装したろ！｣

`visibiliy: none` を使って要素を消し、チェックボックスを自分で作るやり方です。
しかしこれもNG、同じくスクリーンリーダーに反応してくれなく、アクセシビリティが下がってしまいます。

↓参照

https://developer.mozilla.org/ja/docs/Web/CSS/visibility#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B7%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3%E3%81%AE%E8%80%83%E6%85%AE

> 要素の visibility の値に hidden を使用すると、 アクセシビリティツリーから削除されます。これは要素及びその子孫要素が読み上げ技術でアナウンスされない結果になります。

## 彡(ﾟ)(ﾟ)｢せや！んじゃ `appearance: none` で消して実装したろ！｣

`apperance: none`を使ってチェックボックスにデフォルトでつけられているスタイルを消し、自分でスタイリングするやり方です。

この実装はOKです！
`apperance: none`は 既存のCheckboxに割り振られたスタイルを打ち消す効果があります。
よって、チェックボックス自体を消すわけではありません。
なのでスクリーンリーダーにもしっかり読み上げてもらうことが可能です。



↓参照

https://developer.mozilla.org/ja/docs/Web/CSS/appearance


`appearance: none`
> appearance は CSS のプロパティで、 OS のテーマに基づいたプラットフォームネイティブのスタイル付けを使用して要素を表示するために使用されます

また、`appearance: none`を使った方法は一番カスタムチェックボックスを作るのが簡単な実装方法です。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="eYQYPBE" 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/eYQYPBE">
  Untitled</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>

上記が私が一番簡単だと思うカスタムチェックボックスの実装方法です。
多分これが一番楽だと思います。

チェックのアイコンは外部のものを使用して実装しています。
Fontawesomeなどのアイコンを使った簡単なカスタムチェックボックスを作る際は是非参考にしてみてください。

また、アイコンを使わずに**borderを使って自分でチェックマークを作る**ことも可能です。こちらの実装も是非参考にしてみてください。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="PoxoyvN" 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/PoxoyvN">
  Untitled</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>


こちらの実装は、チェックマークの位置を `top`, `left` で微調整していきます。
なので **変なpx数を設定する可能性があります。**
実際に私の実装の方でも `left: 7.4px` となんとも微妙な数字を指定してます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/2147a300-a654-745f-77b1-055fb850ac03.png)


なのでチェックマークを自力で作るのであれば許容ですが、あまりお勧めはしません。
(できればチェックアイコンを使って実装することを願いましょう)

## 彡(ﾟ)(ﾟ)｢せや！んじゃ！ `oppacity: 0`で消して実装したろ！｣

`oppacity: 0`を使ってチェックボックスの不透明度を0にし、見えないようにする実装する方法です。

これもありだと思います！
透明にすることで、実態を残すことができるのでスクリーンリーダーにも読み上げてくれます。
そして、`oppacity: 0`を使った実装方法はおそらくこのようになると思います。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="GRwRwNj" 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/GRwRwNj">
  Opacity: 0で作成した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>

`opacity: 0` を使うメリットですが、チェックマークで `<i>` が使えることだと思います。
先ほどの `appearance: none` では CSSの`content`を利用しないと再現できないので、 `<i>` を使うことが出来ません。
なので、何かしらの理由でチェックマークもCSSでなく `<i>` を使いたい場合はこちらで実装するのが良いでしょう。
(cssで要素を追加するのでなく要素自体は全てhtmlで管理したいなど)

そして、`opacity: 0` を使うデメリットとしては、CSSが複雑になりコード量が増える。ということが挙げられます。
`appearance: none`はデフォルトのスタイルを消し上書きを行なっている実装方針なのでそこまでcssコードは増えません。
それに対し、`opacity: 0`はデフォルトのチェックボックスを消し、自分で０からカスタムチェックボックスを作ります。
なので、その分cssのコードは増えてしまうわけです。


### 複雑なチェックマークを表現したい場合でも `opacity: 0` は有能

![UniConverter_20230607235339.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293066/5db4978e-f94c-2ac8-852d-6e9137d729da.gif)
サービスによっては画像の様にアニメーションを付けたチェックボックスを作りたい場合もあるかもしれません。

そのような複雑なチェックボックスを実装する場合も `opacity: 0` で作ったほうが汎用性があり複雑なチェックボックスを実装することが可能になっています。
コードはこちらに貼っておくので参考にしてみてください。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="QWJWJgm" 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/QWJWJgm">
  opacity: 0を使ったアニメーションがある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>



## まとめ
ということで今回、カスタムチェックボックスについてアクセシビリティの観点を踏まえて、事細かに説明してみました。
色んなサイトを見ていると `display: none` で実装されているのが多くありました。ここ最近のアクセシビリティの注目的に、アクセシビリティをしっかり考慮したコンポーネントはとても大事になってきています。

是非、この記事がアクセシビリティを考慮したコンポーネント作成に役立つことを願っています。
ではまた機会がありましたら別の記事でお会いしましょう。ノシ


（今回作ったCheckboxを全部まとめたやつを貼っておきます）

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JjmQbaG" 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/JjmQbaG">
  CustomCheckbox</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>