yasuda

キーボード操作もできるアクセシブルなチェックボックスとラジオボタンをCSSでカスタマイズする

チェックボックスやラジオボタンは、「閲覧環境によってデザインが変わってしまう」「サイトのデザインと合わない」といった理由からCSSでカスタマイズすることが多いと思います。

ただ、検索でよく見るカスタマイズ方法だと、inputタグをdisplay: none;で非表示にするので、フォーカスが当たらずキーボードでの操作ができなくなってしまうものが多いです(スクリーンリーダーの読み上げがされないこともあるそうです)。

キーボード操作の機能を残したまま、CSSでカスタマイズする方法を紹介します。


2017年9月8日補足
アクセシビリティの情報を発信されている「AccSell(アクセル)」のポッドキャストに取り上げていただきました。

第123回: 「音声ファーストインデックス」|ポッドキャスト|AccSell

そこで以下のような点を指摘していただきました。

  • background-imageプロパティはWindowsのハイコントラストモードでは表示されず、背景べた塗りのような表示になってしまう。
  • フォーカスリングも表示されないため、ハイコントラストモードでキーボード操作するとほとんど使えなくなってしまう。
  • 見た目をCSSで指定していてコード的には正しいとも感じる。クライアント側で制御する問題という側面もありそう。
  • Windows10のEdgeなら背景画像も表示されるように変更されたらしい。

Windows10のIE11とEdgeで検証したところ、ハイコントラストモードでチェックボックスなどのアイコン部分が真四角の塗りつぶし状態になっており、フォーカスリングも表示されないため、キーボードでの操作が困難であることを確認しました。

背景画像の代わりにアイコンフォントを使うことも検討しているのですが、サイズや位置の調整が難しいため、ハイコントラストモードと印刷のときにスタイルを上書きする方法で対処、コードも追加しています。

デモ

デモを用意したので確認してみてください。

チェックボックスはtabキーとshift + tabでフォーカスの切り替え、spaceキーでチェックボックスをチェックすることができます。
ラジオボタンはtabキーとshift + tabでフォーカス、矢印キーの上下左右でフォーカスの切り替えができます。

Macを使っていてフォーカスが当たらない場合は、[システム環境設定.app]を開き、[キーボード][ショートカット]と選択し、フルキーボードアクセスの[すべてのコントロール]にチェックを入れてください。

HTML

HTMLは以下のようになります。

<input type="checkbox" id="checkbox1" checked="checked" class="Checkbox">
<label for="checkbox1">チェックボックス1</label>

<input type="checkbox" id="checkbox2" class="Checkbox">
<label for="checkbox2">チェックボックス2</label>
<input type="radio" id="radio1" name="radio1" checked="checked" class="Radio">
<label for="radio1">ラジオボタン1</label>

<input type="radio" id="radio2" name="radio1" class="Radio">
<label for="radio2">ラジオボタン2</label>

inputlabelid属性とfor属性でひも付けます。inputタグにだけ.Checkbox.Radioというようにクラス名を付けています。

CSS

CSSは以下のようになります。

/* フォーカスや音声読み上げは残したまま非表示にする。 */
.Checkbox {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  overflow: hidden;
  padding: 0;
  clip: rect(0, 0, 0, 0);
}

.Checkbox + label {
  display: inline-block;
  position: relative;
  padding-left: 1.25em;
  cursor: pointer;
}

/* 擬似要素で楕円を作る。 */
.Checkbox + label:before {
  content: "";
  display: inline-block;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 1em;
  height: 1em;
  margin: auto;
  border: 1px solid #767676;
  border-radius: 3px;
  background-repeat: no-repeat;
  background-size: contain;
}

/* フォーカスが当たると楕円の色などを変える。 */
.Checkbox:focus + label:before {
  border-color: #1589ee;
  box-shadow: 0 0 5px #1589ee;
}

/* チェックボックスがチェックされるとボーダーは非表示、画像でチェックボックスを表示する。 */
.Checkbox:checked + label:before {
  border: 0;
  background-image: url("../img/Checkbox_on.svg");
}

/* disabled(非活性)時にはスタイルを変える。 */
.Checkbox:disabled,
.Checkbox + label[disabled] {
  cursor: not-allowed;
  opacity: 0.5;
}

ラジオボタンもチェックボックスとほとんど同じです。

.Radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  overflow: hidden;
  padding: 0;
  clip: rect(0, 0, 0, 0);
}

.Radio + label {
  display: inline-block;
  position: relative;
  padding-left: 1.25em;
  cursor: pointer;
}

.Radio + label:before {
  content: "";
  display: inline-block;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 1em;
  height: 1em;
  margin: auto;
  border: 1px solid #767676;
  border-radius: 50%;
  background-repeat: no-repeat;
  background-size: contain;
}

.Radio:focus + label:before {
  border-color: #1589ee;
  border-radius: 50%;
  box-shadow: 0 0 5px #1589ee;
}

.Radio:checked + label:before {
  border: 0;
  background-image: url("../img/Radio_on.svg");
}

.Radio:disabled,
.Radio + label[disabled] {
  cursor: not-allowed;
  opacity: 0.5;
}

ポイントとしては、

  • チェックボックス(.Checkbox)やラジオボタン(.Radio)は操作できる状態のまま非表示にする
  • 隣接セレクタ(E + E)によって、チェックボックスの直後にあるlabelタグにチェックボックスやラジオボタンを表示させる
  • padding-leftでアイコンのスペースを確保、アイコンにtop: 0; bottom: 0; margin: auto;を指定することで垂直位置が中央になるように指定する
  • チェックボックスやラジオボタンにフォーカスが当たったときと、チェックされたときの両方にスタイルを指定する
  • disabled(非活性)時のスタイルも忘れず指定する

2017年9月8日追記
印刷時とハイコントラストモードでアイコンが表示されるようにするスタイルです。背景画像のアイコンを非表示にして、HTMLタグのデフォルトのアイコンを表示します。

/**
 * 印刷時とハイコントラストモード(IEとEdge)が有効なときのスタイル。
 */
@media screen and (-ms-high-contrast: active), print {
  .sw-FormCheckbox,
  .sw-FormRadio {
    position: static;
    width: auto;
    height: auto;
    margin: auto;
  }

  .sw-FormCheckbox + label,
  .sw-FormRadio + label {
    padding-left: 0;
  }

  .sw-FormCheckbox + label:before,
  .sw-FormRadio + label:before {
    display: none;
  }
}

さいごに

CSSでカスタマイズしたときは、そのHTMLの要素が本来持っている機能が損なわれていないか確認してみてください。僕自身、あまりキーボードでフォーカスを移動しないので見落としてしまっていましたが、以下のような利用者の状況によってはキーボード操作ができなくて不便なときがあります。

  • 手をケガしていてマウスが持てない(持ちにくい)
  • マウスをなくしてしまった
  • トラックパッドが動かなくなってしまった(電池切れ・故障)
  • 目が見えにくい(見えない)のでキーボードとスクリーンリーダーで閲覧している

操作できることを担保しないと、利用者に「知ってもらうこと」や「買ってもらうこと」につながらなくなってしまう恐れがあります。見落としがちなところですが、大切なことなのでしっかりと考えてコーディングしていきたいですね。

参考リンク

新しいウェブ体験を作ろう TAMのPWA開発
お問い合わせはこちら