見出し画像

【Nuxt.js】アクセシビリティとコンポーネント化を考えたcheckbox

🎈 WPでも公開中です
https://wp.me/pc9NHC-1kc

#vue #nuxt #プログラミング #エンジニア

前置き

input type="checkbox"
といえばこのデザイン

画像1

これをカスタムすると
色や形も自由に変更できます✨

画像2

ただCSSでデザインできる💫
とわかっていても
毎回ググっては読み解くのに
時間がかかったため
シンプルに理解できるよう
記事にしました🔍📚

また、ほとんどのサイトでは
inputlabelで囲まず、
labelに装飾をするパターンです。
inputdisplay: none;
label::beforeで枠線
label::afterでチェック部分を装飾。

ただ個人的にそれだけCSSを書くなら
コンポーネントにしたい❗️
そしてNuxtの場合
templateの直下タグを
1つにできるならそうしたいので
template > label > input
にしたいのです💡

それからdisplay: none;
キーボード操作ができない💥
ということを知りました。
そう、アクセシビリティ
(利用のしやすさ)が低いのです🤔💭
こちらを参考にしています👇

多くのサイトで紹介されているチェックボックスはdisplay: none;を使ったカスタマイズであるため、キーボードを使った選択操作ができません。

解決方法はシンプルです。input要素をdisplay: none;にするのではなく、widthを0にします。こうすることでタブによるフォーカスやスペースによる選択ができるようになります。
【コピペ可】HTMLとCSSでチェックボックスのコーディング4選

⬇️以前switchボタンで
 input type="checkbox"の
 装飾をしているのですが…

まずはチェックボックスを
どうデザインするのか
説明がわかりにくいと思ったので
チェックボックスに要点を絞ったものを
書きたいな〜✍️
と思っていたのです🍀

ということで今回は
ディレクティブなどは置いておき、
コンポーネントの大まかな構造と
CSSをどうあてるかを書いています❗️

$emitなどもまとめて書いたコードは
今度公開予定です🌟

参考:
【コピペ可】HTMLとCSSでチェックボックスのコーディング4選
アクセシビリティで気をつけるcheckbox,radioのCSS


構造理解

画像3

全体の構成を理解していきます。
input自体に装飾はできないため、
spanで装飾をしていきます。

<template>
 <label class="label">
   <input class="input" type="checkbox" />
   <span class="mark"></span>
   <span class="text">{{ text }}</span>
 </label>
</template>

そのためinputはCSSで
非表示にする必要がありますが、
今の段階では、
あえて隠していません。
inputspan
連動させることを
分かりやすくするためです🪐

あとは
擬似クラス:checked
擬似要素::beforeなどを使用して
inputと連動させながら装飾をしていくだけです🌟

<style lang="scss" scoped>
.label { // コンポーネント全体

 &:hover > .mark { // hoverした時
 }

 .input {
   margin: 0;
   // width: 0;
   // opacity: 0;
 }

 .input:focus + .mark { // focusした時の装飾枠
 }

 .input:checked + .mark { // checkした時の装飾枠
 }

 .input:checked + .mark::before { // checkした時の装飾枠内のチェック
 }

 .mark { // 装飾枠
 }
}
</style>

.input:focus + .mark
:focus
隣接セレクタ(+)
inputをクリックした時のmark
となるため、
mark部分がinputと連動するわけです💫☝️

.input:checked + .mark
:checked
こちらも:focusと同様に
inputをチェックした時のmark
ということで連動しています

&:hover > .mark
子セレクタ、直下セレクタ(>)
&はscssで親を指すので
.labelのことです。
labelをhoverした時のmark

⬇️セレクタについては
 こちらも参考になります
 2011年の記事ですが、
 一覧で見れるのはメリットです🌟
意外と知らない!?CSSセレクタ20個のおさらい


コード

画像4

そしてinputdisplay: none;
にはしていないので、
キーボード操作が可能です。
tabキーでinputまで移動し
スペースを押すと選択ができます。

<template>
 <label class="label">
   <input class="input" type="checkbox" />
   <span class="mark"></span>
   <span class="text">{{ text }}</span>
 </label>
</template>

<script>
export default {
 props: {
   text: {
     type: String,
     required: false,
     default: '',
   },
 },
}
</script>

<style lang="scss" scoped>
.label {
 padding: 12px 8px;
 display: flex;
 align-items: center;
 cursor: pointer;

 &:hover > .mark {
   background: #dddddd !important;
   border: solid 2px #008eff;
 }

 .input {
   margin: 0;
   width: 0;
   opacity: 0;
 }

 .input:focus + .mark {
   background: #dddddd !important;
   border: solid 2px #008eff;
 }

 .input:checked + .mark {
   border: solid 2px #008eff;
   background: #ffffff;
 }

 .input:checked + .mark::before {
   content: '';
   display: block;
   position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -45%);
   width: 80%;
   height: 80%;
   background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="%23008EFF" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg>')
     no-repeat center;
   background-size: contain;
 }

 .mark {
   position: relative;
   top: 0;
   left: 0;
   display: block;
   width: 32px;
   height: 32px;
   border: solid 2px #93cfff;
   background: #ffffff;
   border-radius: 4px;
 }

 .text {
   margin-left: 12px;
   display: block;
   font-size: 18px;
   font-weight: bold;
 }
}
</style>
<template>
 <div class="page">
   <FormItemInputCheck text="同意する" />
 </div>
</template>

アイコンはiconmonstrを使用🍒
background-image
svgを適応させています。
svgコードはiconmonstrコピペして
pathの後ろにfillを追加するだけです。
カラーコードの#
%23にする必要があります。
#008EFFを使用したかったので
%23008EFFになります。

とりあえずdata:image/svg+xmlして
svgコードつけてfillで色つければOKです🙆‍♀️
ベースのコードはこちら❗️

background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="%23008EFF" d="省略"/></svg>')no-repeat center;


まとめ

これでアクセシビリティを高め
コンポーネントの作成もしやすく
スタイリングも
分かりやすくなりました✨👏

🎈 WPでも公開中です
https://wp.me/pc9NHC-1kc


この記事が気に入ったらサポートをしてみませんか?