複数の選択肢を1つの枠に収めて省スペースを実現する部品。「5〜15個」の選択肢に最適で、それ以外はRadioまたはComboboxに切り替える判断が核になる。
Selectは省スペースに見えますが、開くまで選択肢が見えないため、ヒックの法則と選択肢の最適化の影響を強く受けます。フォーム設計では、少数の選択肢ならラジオ、階層的な操作ならドロップダウンメニューと比較して選びます。
この記事を読むと、Select / Radio / Comboboxの使い分け・状態設計・A11y実装の判断が自分でできるようになります。
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
あらかじめ用意された複数の選択肢から、ユーザーに1つの値を選ばせる入力コンポーネント。「開かないと中身が見えない」省スペース型UIで、選択肢が5〜15個のときに最適。
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- 選択肢が5〜15個程度あるとき
- 画面スペースが限られており、全選択肢を常時表示できないとき
- デフォルト値があり、ほとんどのユーザーが変更しないと予測されるとき
3.2 When NOT to use
- 選択肢が4個以下(Radio Buttonを使う → ワンクリックで選べる)
- 選択肢が15個以上・または検索が必要(Comboboxを使う)
- 複数選択が必要(Checkbox群 / Multi-Selectを使う)
3.3 代替UI(Alternatives)
- 2〜4択 →
Radio Button - 15択以上・検索あり →
Combobox - 複数選択 →
Checkbox/Multi-Select - 日付選択 →
Calendar / DatePicker
4. 設計判断の核(Decision Principles)
「開く1手間」に見合う省スペース効果があるかで選ぶ。
判断の優先順位:① 選択肢の数(4以下→Radio、5〜15→Select、15超→Combobox) → ② 複数選択の有無 → ③ 検索の必要性 → ④ デフォルト値の有無
- Selectは「選ばせること」より「リストを収容すること」が目的
- ラベルは必ず枠外に常時表示する
- 選択後に選んだ値が枠内に正しく表示されること
- 並び順は頻出順 / あいうえお順 / 時系列など論理的なルールに従う
5. 状態設計(States)
5.1 必須状態(Required)
- Default:現在値またはプレースホルダーを表示。右端にChevron(▼)
- Focus:フォーカスリングを明確に表示(省略不可)
- Open:リストが展開。現在選択値をハイライト
- Disabled:枠線・テキストをグレーアウト。
cursor-not-allowed
5.2 条件付き状態(Conditional)
- Error:未選択エラーなど。枠線を赤くしメッセージを下に表示
- Hover:Chevronや枠の色を変化させインタラクティブと示す
5.3 State Gallery
| 状態 | 必須 | 何を伝えるか |
|---|---|---|
| Default | ✅ | 選択可能であることを示す |
| Focus | ✅ | 今ここにいることをキーボードユーザーに示す |
| Open | ✅ | 選択肢が展開されていることを示す |
| Disabled | ✅ | 今は選択できないことを示す |
| Error | — | 未選択または不正な選択を伝える |
| Hover | — | 選択できることをマウスユーザーに強調する |
6. バリエーション設計(Variants)
見た目ではなく、選択肢の数と文脈でUIを切り替える。
| 選択肢数 | 推奨コンポーネント | 理由 |
|---|---|---|
| 1〜4個 | Radio Button | 全選択肢が常時見えるためワンクリックで選べる |
| 5〜15個 | Select | 省スペースでリストを収容できる |
| 16個〜 | Combobox | スクロール地獄を防ぐために検索機能が必要 |
禁止パターン:2択のSelectを使う → 「開いて選ぶ」1ステップが余分になる
併用の指針:フォーム内で Select と Radio が混在する場合は、選択肢数で統一ルールを設ける
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- 選択肢が少なすぎるSelect:「はい / いいえ」2択にSelectを使い、余計な1クリックをユーザーに強要する
- 選択肢が多すぎるSelect:100国以上のリストをSelectで並べ、スクロール地獄を生む
- 現在値の喪失:ラベルがなく開く前から何を選ぶ枠か分からない、または選択後に値が枠からはみ出す
7.1 Bad(典型3つ)
<select>に<option value="">選択してください</option>だけあり、ラベルなし → 何を選ぶ欄か分からない- 都道府県47件をSelectで表示しているが上から順に並んでいるだけ → 探しにくい
- 選択後に選んだ値が長くて枠からはみ出している → 何を選んだか確認できない
7.2 Good(対になる3つ)
<label>を枠の上に常時表示し、プレースホルダーに「選択してください」を補足- 都道府県は地方別グループ + 頻出エリアを先頭に配置(
<optgroup>活用) - 選択値のテキストが長い場合は
text-ellipsis+overflow-hiddenで枠内に収める
7.3 How to fix(手順)
- 選択肢の数を数える → 4以下ならRadio、15以上ならComboboxへ切り替える
<label>を枠の外側に常時表示する- 頻出・重要な選択肢を先頭に配置し、グループ分けを検討する
- デフォルト値があれば初期選択状態にしておく
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Keyboard
Tabでフォーカスし、Enter/Space/↑↓でリストを展開できること- リスト展開中は
↑↓で項目を移動、Enterで確定、Escでキャンセルできること
Focus
- Selectのトリガーにフォーカスリングを明確に表示する
Screen Reader
aria-haspopup="listbox"とaria-expandedで展開状態を伝える- 選択肢は
role="listbox"とrole="option"で関連付ける
<label for="dept">部門</label>
<button id="dept" aria-haspopup="listbox" aria-expanded="false">
デザイン
</button>
<ul role="listbox" aria-labelledby="dept">
<li role="option" aria-selected="true">デザイン</li>
<li role="option" aria-selected="false">エンジニアリング</li>
</ul>
Touch / Pointer
- タップしやすい高さ(44px以上)を確保する。リスト内の各行も同様
10. 実装メモ(Implementation Notes)
<select>のネイティブ要素はモバイルでOSのドラムロールUIを呼び出せるため、カスタムUIより安定した体験を提供できることが多い- カスタムSelectを実装する場合、
useEffectでクリック外側を検知して閉じる処理(outside click)を忘れずに - Popoverの位置計算は
getBoundingClientRect()でViewport端を確認し、上下どちらに展開するか動的に切り替える
11. 関連リンク
- 関連するUIデザイン原則: フィードバック (Feedback), Fittsの法則 (Fitts's Law)
- 用語集(定義): アクセシビリティ (Accessibility)
- 関連するUIコンポーネント(横): Checkbox(チェックボックス), Text Input(テキスト入力)
まとめ
Selectの設計判断は「選択肢の数」で9割決まります。迷ったら 4. 設計判断の核 に戻り、4以下ならRadio・15超ならComboboxへの切り替えを検討してください。選択後に「何を選んだか」が明確に表示されることが、ユーザーの安心感の核心です。