セレクト
ボタンを押すとリストボックスが開くカスタムのセレクト。矢印キー・Enter・Escで操作でき、選択中の項目にはチェックが付く。
プレビュー
クリック
操作クリック/タップで動きます。
仕様書
- 向く場面
- プラン・地域など数個〜十数個から1つ選ぶ入力
- ネイティブ select より見た目を揃えたいフォーム
- 選択中にチェック印を付けたいメニュー
- 避ける場面
- 候補が多く検索が要る(コンボボックス)
- 複数選択
- 構成要素
- ラベル
- トリガーボタン(現在値・矢印)
- リストボックス
- 選択肢(チェック印)
- 持っている状態
- 通常
- ホバー
- フォーカス
- 押下中
- キーボード
ボタンで ↓/Enter/Space で開く。↑↓ で候補を移動、Home/End で端へ、頭文字で該当候補へジャンプ。Enter/Space で確定、Esc で閉じてボタンへ戻る
- 支援技術
APG select-only combobox: ボタンに role=combobox・aria-haspopup・aria-expanded・aria-controls・aria-activedescendant。ul は listbox、li は option+aria-selected。選択はチェック印+太字
- 動き
矢印の回転 200ms、枠・リング 180ms、候補背景 120ms。reduced-motion で無効
原則一貫性と標準
目的選ばせる
デザインの要点
- フォーカスはボタンに留め、リスト内の位置は aria-activedescendant で伝える。リストへフォーカスを移すと Esc で戻す処理が要る
- 開いたときのハイライトは選択中の項目に置く。先頭固定だと、いまの値を確かめるために一度スクロールさせる
- 選択中はチェック印+太字。ハイライト(背景色)と混ぜると「選ばれている」と「いま指している」が区別できない
- 候補が十数個を超えて検索が要るならコンボボックスへ。セレクトは目で全部見渡せる数までにする
実装メモ
ネイティブの <select> ではなく button(role="combobox")+ role="listbox" で組み、選択中は aria-selected とチェックマークで示します。フォーカスはボタンに保ち、矢印キーで active(視覚ハイライト)を移動して aria-activedescendant で位置を伝え、Enterで確定・Escで閉じる APG の select-only combobox の型です。
コード(コピーして使えます)
<div class="sd-wrap">
<span class="sd-label" id="sd-label">プラン</span>
<div class="sd-field">
<button
class="sd-button"
id="sd-button"
type="button"
role="combobox"
aria-haspopup="listbox"
aria-expanded="false"
aria-controls="sd-list"
aria-labelledby="sd-label sd-value"
>
<span class="sd-value" id="sd-value">選択してください</span>
<svg class="sd-caret" width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
<polyline points="3,5 7,9 11,5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<ul class="sd-list" id="sd-list" role="listbox" aria-labelledby="sd-label" tabindex="-1" hidden>
<li class="sd-option" id="sd-opt-free" role="option" data-value="free" aria-selected="false">
<span class="sd-check" aria-hidden="true">✓</span>Free(無料)
</li>
<li class="sd-option" id="sd-opt-pro" role="option" data-value="pro" aria-selected="false">
<span class="sd-check" aria-hidden="true">✓</span>Pro(月額 980円)
</li>
<li class="sd-option" id="sd-opt-team" role="option" data-value="team" aria-selected="false">
<span class="sd-check" aria-hidden="true">✓</span>Team(月額 2,980円)
</li>
<li class="sd-option" id="sd-opt-enterprise" role="option" data-value="enterprise" aria-selected="false">
<span class="sd-check" aria-hidden="true">✓</span>Enterprise(要問合せ)
</li>
</ul>
</div>
</div>