Skip to content

Day 4: カスタムフォーム UI — 見た目を変えてもアクセシビリティを保つ

今日のゴール

  • フォーム部品の見た目をカスタマイズする場面があることを知る
  • 見た目だけ変えても、裏で壊れていることがあると知る
  • 部品によってカスタマイズの方法が違うことを知る

フォーム部品の見た目はカスタマイズできる

チェックボックスやラジオボタンなどのフォーム部品は、ブラウザや OS によって見た目が異なります。プロジェクトのデザインに合わせるために、見た目のカスタマイズが求められることがあります。

どのくらい違うのか、デモで見比べてみてください:

ブラウザ標準
カスタマイズ後

どちらもクリックで切り替わりますが、見た目の印象はまったく違います。ただし、見た目を変えるのは簡単ではありません。やり方を間違えると、見た目は変わっても裏側で壊れてしまうことがあります。

見た目は動いていても、ちゃんと動いているとは限らない

HTML 標準のフォーム部品(<input type="checkbox"> など)には、見た目以上にたくさんの機能が組み込まれています。カスタマイズの方法によっては、これらの機能が失われてしまうことがあります。

機能HTML 標準の部品見た目だけ作ったもの
クリックで切り替え動く動くこともある
キーボード(Space キー)で切り替え動く動かない
Tab キーでフォーカス移動動く動かない
スクリーンリーダーの読み上げ読む読まない
<form> 送信で値が送られる送られる送られない
ブラウザの自動入力対応非対応

クリックで動いているように見えても、キーボードでは操作できない、フォームで送信されない、といった問題が隠れていることがあります。AI が生成したコードでも、こうした品質の差は起こりえます。

見た目を変えても、HTML 標準の機能を壊さないことが大切です。

やり方は部品によって違う

ここからは、具体的なカスタマイズの方法を見ていきます。部品によってやり方や難易度が大きく異なります。

CSS だけでいけるもの: checkbox / radio / file

checkbox や radio は、HTML 標準の <input> を残したまま、見た目だけ CSS で差し替えることができます。

やり方:

  1. 本物の <input> を目に見えないように隠す
  2. 隣に置いた要素で好きな見た目を作る
  3. ユーザーの操作は裏の <input> が受け取る

<input> が裏にいるので、キーボード操作もフォーム送信もスクリーンリーダーもそのまま動きます。

html
<label class="custom-checkbox">
  <!-- 本物の input。sr-only で視覚的に隠す -->
  <input type="checkbox" class="sr-only" name="agree" />
  <!-- 見た目用の要素 -->
  <span class="checkbox-visual"></span>
  利用規約に同意する
</label>
css
/* 視覚的に隠すが、スクリーンリーダーからはアクセスできる */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

/* チェックされたら隣の要素の見た目を変える */
.sr-only:checked + .checkbox-visual {
  background-color: #2563eb;
  border-color: #2563eb;
}

/* キーボード操作時のフォーカスリング */
.sr-only:focus-visible + .checkbox-visual {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

ポイント:

  • sr-only: display: none だとスクリーンリーダーからも消える。sr-only なら「見えないがアクセスできる」状態になる(Tailwind CSS にも同名のクラスあり)
  • :checked: チェック状態に応じて CSS だけで見た目が切り替わる
  • :focus-visible: Tab 移動時にフォーカスの位置が見えるようにする

同じ考え方で、いろいろな UI をカスタマイズできます。

カード型のラジオボタン

<input type="radio"> を隠して、カード全体をクリック可能にした例です。

プランを選択してください

ファイル選択

<input type="file"> も同じです。ボタンの見た目だけ変えて、ファイル選択ダイアログ自体はそのまま使います。

ブラウザ標準
カスタマイズ後

CSS だけでは無理なもの: select

<select> のドロップダウン部分は OS のネイティブ UI として描画されるため、CSS ではほぼカスタマイズできません。

↑ ボタン部分はスタイリングできるが、ドロップダウン(選択肢リスト)はブラウザ任せ

select をカスタマイズしたいとき、現在は 2 つの選択肢があります。

カスタマイザブル <select> — 標準化中の新しい仕組み

2026 年 4 月時点では Chrome 系ブラウザのみ対応。本番投入には早い段階です

この問題を解決するために、カスタマイザブル <select> という新しい仕組みが標準化されつつあります。

  • CSS で appearance: base-select を指定するだけ
  • ドロップダウンも選択肢もすべてスタイリングできる
  • <select> のまま。キーボード操作もフォーム送信もそのまま

Chrome 系ブラウザならデモで確認できます(Safari / Firefox では通常の <select> として表示されます):

↑ Chrome 系ブラウザでは、ドロップダウンもスタイリングされて表示される

将来的にはこれが標準的な方法になりそうですが、まだすべてのブラウザでは使えません。

ヘッドレス UI ライブラリ — 現時点の解決策

select を手動でカスタマイズしようとすると、キーボード操作、フォーカス制御、スクリーンリーダー対応など、考慮すべきことが非常に多くなります。

そこで便利なのがヘッドレス UI ライブラリです。「ヘッドレス」= 見た目がない、という意味で、こうした面倒な部分をライブラリが引き受けてくれます。

  • ライブラリが担当: キーボード操作、ARIA 属性の管理、フォーカス制御
  • 開発者が担当: 見た目(CSS)

React Aria(Adobe 製)などを使えば、開発者はスタイリングだけに集中できます。

まとめ

  • フォーム部品の見た目はブラウザと OS が決める。デザインに合わせるカスタマイズは実務で必須
  • 見た目が動いていても、キーボード操作やスクリーンリーダー対応が壊れていることがある
  • checkbox / radio / file は CSS だけでカスタマイズできる。HTML 標準の <input> を残して見た目だけ被せる
  • select は CSS だけでは無理。カスタマイザブル <select>(標準化中)かヘッドレス UI ライブラリを使う