Appearance
Day 4: カスタムフォーム UI — 見た目を変えてもアクセシビリティを保つ
今日のゴール
- フォーム部品の見た目をカスタマイズする場面があることを知る
- 見た目だけ変えても、裏で壊れていることがあると知る
- 部品によってカスタマイズの方法が違うことを知る
フォーム部品の見た目はカスタマイズできる
チェックボックスやラジオボタンなどのフォーム部品は、ブラウザや OS によって見た目が異なります。プロジェクトのデザインに合わせるために、見た目のカスタマイズが求められることがあります。
どのくらい違うのか、デモで見比べてみてください:
ブラウザ標準
カスタマイズ後
どちらもクリックで切り替わりますが、見た目の印象はまったく違います。ただし、見た目を変えるのは簡単ではありません。やり方を間違えると、見た目は変わっても裏側で壊れてしまうことがあります。
見た目は動いていても、ちゃんと動いているとは限らない
HTML 標準のフォーム部品(<input type="checkbox"> など)には、見た目以上にたくさんの機能が組み込まれています。カスタマイズの方法によっては、これらの機能が失われてしまうことがあります。
| 機能 | HTML 標準の部品 | 見た目だけ作ったもの |
|---|---|---|
| クリックで切り替え | 動く | 動くこともある |
| キーボード(Space キー)で切り替え | 動く | 動かない |
| Tab キーでフォーカス移動 | 動く | 動かない |
| スクリーンリーダーの読み上げ | 読む | 読まない |
<form> 送信で値が送られる | 送られる | 送られない |
| ブラウザの自動入力 | 対応 | 非対応 |
クリックで動いているように見えても、キーボードでは操作できない、フォームで送信されない、といった問題が隠れていることがあります。AI が生成したコードでも、こうした品質の差は起こりえます。
見た目を変えても、HTML 標準の機能を壊さないことが大切です。
やり方は部品によって違う
ここからは、具体的なカスタマイズの方法を見ていきます。部品によってやり方や難易度が大きく異なります。
CSS だけでいけるもの: checkbox / radio / file
checkbox や radio は、HTML 標準の <input> を残したまま、見た目だけ CSS で差し替えることができます。
やり方:
- 本物の
<input>を目に見えないように隠す - 隣に置いた要素で好きな見た目を作る
- ユーザーの操作は裏の
<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 ライブラリを使う