25. select / option(選択UI)
まず結論
候補が決まっている選択はselectで作ると、入力ミスを減らしつつ確実に値を送れます。
最小の書き方(コピペで動く最小コード)
HTMLCode
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Select Minimum</title>
</head>
<body>
<form action="/submit" method="post">
<label for="plan">プラン</label>
<select id="plan" name="plan">
<option value="light">ライト</option>
<option value="standard">スタンダード</option>
<option value="pro">プロ</option>
</select>
<button type="submit">送信</button>
</form>
</body>
</html>
Previewdesktop
HTMLCode
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Select Minimum</title>
</head>
<body>
<form action="/submit" method="post">
<label for="plan">プラン</label>
<select id="plan" name="plan">
<option value="light">ライト</option>
<option value="standard">スタンダード</option>
<option value="pro">プロ</option>
</select>
<button type="submit">送信</button>
</form>
</body>
</html>
Preview を表示
重要ポイント(ここで迷いがち)
- selectは候補から選ぶ箱、optionは候補1つ
- 送信されるのは「selectのname」と「選ばれたoptionのvalue」
- 画面に見える文字:ライト
- 送信値:
value="light"
- labelで必ず紐付ける(#21)
label for="plan"↔select id="plan" - 未選択を許したくないなら“プレースホルダー的option”を用意
value="" + disabled selectedで「選んでください」を作る(下の例) - 初期選択はselected
ただし“意図せず勝手に選ばれている”と誤送信が増えるので注意
例で理解(よく使うパターン 5つ)
1) 「選んでください」を先頭に置く(実務で超よくある)
HTMLCode
<label for="pref">都道府県</label>
<select id="pref" name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
<option value="aichi">愛知県</option>
</select>
Previewdesktop
HTMLCode
<label for="pref">都道府県</label>
<select id="pref" name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
<option value="aichi">愛知県</option>
</select>
Preview を表示
requiredと合わせると「未選択」のまま送れません。
2) 既定値を選んでおく(設定画面など)
HTMLCode
<label for="notify">通知</label>
<select id="notify" name="notify">
<option value="on" selected>受け取る</option>
<option value="off">受け取らない</option>
</select>
Previewdesktop
HTMLCode
<label for="notify">通知</label>
<select id="notify" name="notify">
<option value="on" selected>受け取る</option>
<option value="off">受け取らない</option>
</select>
Preview を表示
3) optgroupでカテゴリ分け(候補が多いとき)
HTMLCode
<label for="course">コース</label>
<select id="course" name="course">
<optgroup label="入門">
<option value="html">HTML</option>
<option value="css">CSS</option>
</optgroup>
<optgroup label="発展">
<option value="js">JavaScript</option>
<option value="react">React</option>
</optgroup>
</select>
Previewdesktop
HTMLCode
<label for="course">コース</label>
<select id="course" name="course">
<optgroup label="入門">
<option value="html">HTML</option>
<option value="css">CSS</option>
</optgroup>
<optgroup label="発展">
<option value="js">JavaScript</option>
<option value="react">React</option>
</optgroup>
</select>
Preview を表示
4) 表示名と送信値を分ける(値は短く・安定に)
HTMLCode
<label for="time">希望時間</label>
<select id="time" name="time">
<option value="am">午前</option>
<option value="pm">午後</option>
</select>
Previewdesktop
HTMLCode
<label for="time">希望時間</label>
<select id="time" name="time">
<option value="am">午前</option>
<option value="pm">午後</option>
</select>
Preview を表示
5) disabledな選択肢(準備中など)
HTMLCode
<label for="plan2">プラン</label>
<select id="plan2" name="plan">
<option value="light">ライト</option>
<option value="standard">スタンダード</option>
<option value="pro" disabled>プロ(準備中)</option>
</select>
Previewdesktop
HTMLCode
<label for="plan2">プラン</label>
<select id="plan2" name="plan">
<option value="light">ライト</option>
<option value="standard">スタンダード</option>
<option value="pro" disabled>プロ(準備中)</option>
</select>
Preview を表示
使い分け(checkbox/radio/textareaとの違い)
- select:候補が多めで、1つを選ばせたい
- radio:候補が少なく、全部見せたい(2〜5個くらい)
- checkbox:複数選べる必要がある
- textarea:自由入力(文章)
実務のコツ(SEO/安全/アクセシビリティ)
- “選んでください”を必ず入れて誤送信を減らす
何も考えずに最初の項目が送られる事故を防ぎます。 - valueは英字・短く・変えない前提で
サーバーや集計で扱いやすい(表示名が変わってもvalueは固定にできる)。 - 候補が多いならoptgroupで探しやすく
- ラベルは具体的に
×「選択」→ ○「都道府県」「プラン」「希望時間」
NG・禁止例(事故る書き方)
NG1)nameが無い(送信されるキーがない)
HTMLCode
<select id="plan">
<option value="light">ライト</option>
</select>
Previewdesktop
HTMLCode
<select id="plan">
<option value="light">ライト</option>
</select>
Preview を表示
✅ 正:nameを付ける
HTMLCode
<select id="plan" name="plan">
<option value="light">ライト</option>
</select>
Previewdesktop
HTMLCode
<select id="plan" name="plan">
<option value="light">ライト</option>
</select>
Preview を表示
NG2)未選択のつもりが、最初の項目が勝手に送られる
HTMLCode
<select name="pref">
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
</select>
Previewdesktop
HTMLCode
<select name="pref">
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
</select>
Preview を表示
✅ 正:「選んでください」を置く + required
HTMLCode
<select name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
</select>
Previewdesktop
HTMLCode
<select name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
</select>
Preview を表示
NG3)valueを入れずに表示文字に依存(後で変更に弱い)
HTMLCode
<option>ライト</option>
※ このHTML断片は meta / title など表示要素がないため、プレビューは省略しました。
✅ 正:valueを明示
HTMLCode
<option value="light">ライト</option>
※ このHTML断片は meta / title など表示要素がないため、プレビューは省略しました。
NG4)label無し(何の選択か分からない)
placeholderが無いので、特に迷子になりやすい。
✅ 正:labelを付ける
HTMLCode
<label for="p">プラン</label>
<select id="p" name="plan">
<option value="light">ライト</option>
</select>
Previewdesktop
HTMLCode
<label for="p">プラン</label>
<select id="p" name="plan">
<option value="light">ライト</option>
</select>
Preview を表示
見た目を整える(HTML+CSSセット:5例)
色は使わず、線・余白・影・フォーカスで整えます。
例1)基本のselect(フォーム統一)
例1)基本のselect(フォーム統一)
HTMLCode
<div class="field">
<label class="label" for="plan3">プラン</label>
<select class="select" id="plan3" name="plan" required>
<option value="" disabled selected>選んでください</option>
<option value="light">ライト</option>
<option value="standard">スタンダード</option>
<option value="pro">プロ</option>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.field{ display: grid; gap: .35rem; max-width: 520px; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
box-shadow: 0 10px 22px rgba(0,0,0,.06);
background: transparent;
}
.select:focus{
outline: 2px solid currentColor;
outline-offset: 2px;
}Previewdesktop
HTMLCode
<div class="field">
<label class="label" for="plan3">プラン</label>
<select class="select" id="plan3" name="plan" required>
<option value="" disabled selected>選んでください</option>
<option value="light">ライト</option>
<option value="standard">スタンダード</option>
<option value="pro">プロ</option>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.field{ display: grid; gap: .35rem; max-width: 520px; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
box-shadow: 0 10px 22px rgba(0,0,0,.06);
background: transparent;
}
.select:focus{
outline: 2px solid currentColor;
outline-offset: 2px;
}Preview を表示
例2)幅いっぱい(レイアウト崩れ防止)
例2)幅いっぱい(レイアウト崩れ防止)
HTMLCode
<div class="field">
<label class="label" for="pref3">都道府県</label>
<select class="select full" id="pref3" name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
<option value="aichi">愛知県</option>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.field{ display: grid; gap: .35rem; max-width: 520px; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
.full{ width: 100%; }Previewdesktop
HTMLCode
<div class="field">
<label class="label" for="pref3">都道府県</label>
<select class="select full" id="pref3" name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
<option value="aichi">愛知県</option>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.field{ display: grid; gap: .35rem; max-width: 520px; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
.full{ width: 100%; }Preview を表示
例3)“下矢印”をそれっぽく(疑似的)
例3)“下矢印”をそれっぽく(疑似的)
HTMLCode
<div class="select-wrap">
<label class="label" for="time2">希望時間</label>
<select class="select" id="time2" name="time" required>
<option value="" disabled selected>選んでください</option>
<option value="am">午前</option>
<option value="pm">午後</option>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.select-wrap{ position: relative; max-width: 520px; display: grid; gap: .35rem; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
.select-wrap::after{
content: "▾";
position: absolute;
right: 14px;
top: 50%;
transform: translateY(6px);
pointer-events: none;
opacity: .7;
}Previewdesktop
HTMLCode
<div class="select-wrap">
<label class="label" for="time2">希望時間</label>
<select class="select" id="time2" name="time" required>
<option value="" disabled selected>選んでください</option>
<option value="am">午前</option>
<option value="pm">午後</option>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.select-wrap{ position: relative; max-width: 520px; display: grid; gap: .35rem; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
.select-wrap::after{
content: "▾";
position: absolute;
right: 14px;
top: 50%;
transform: translateY(6px);
pointer-events: none;
opacity: .7;
}Preview を表示
例4)グループ(optgroup)でも同じ見た目で
例4)グループ(optgroup)でも同じ見た目で
HTMLCode
<div class="field">
<label class="label" for="course2">コース</label>
<select class="select" id="course2" name="course">
<optgroup label="入門">
<option value="html">HTML</option>
<option value="css">CSS</option>
</optgroup>
<optgroup label="発展">
<option value="js">JavaScript</option>
<option value="react">React</option>
</optgroup>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.field{ display: grid; gap: .35rem; max-width: 520px; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
optgroup{ font-style: normal; }Previewdesktop
HTMLCode
<div class="field">
<label class="label" for="course2">コース</label>
<select class="select" id="course2" name="course">
<optgroup label="入門">
<option value="html">HTML</option>
<option value="css">CSS</option>
</optgroup>
<optgroup label="発展">
<option value="js">JavaScript</option>
<option value="react">React</option>
</optgroup>
</select>
</div>CSSCode
*{ box-sizing: border-box; }
.field{ display: grid; gap: .35rem; max-width: 520px; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
optgroup{ font-style: normal; }Preview を表示
例5)フォームの“カード化”
例5)フォームの“カード化”
HTMLCode
<form class="form-card" action="/submit" method="post">
<div class="field">
<label class="label" for="pref2">都道府県</label>
<select class="select" id="pref2" name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
</select>
</div>
<button class="btn" type="submit">送信</button>
</form>CSSCode
*{ box-sizing: border-box; }
.form-card{
max-width: 560px;
border: 1px solid rgba(0,0,0,.18);
border-radius: 18px;
padding: 1rem 1.1rem;
box-shadow: 0 10px 22px rgba(0,0,0,.08);
display: grid;
gap: .9rem;
}
.field{ display: grid; gap: .35rem; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
.select:focus{
outline: 2px solid currentColor;
outline-offset: 2px;
}
.btn{
min-height: 44px;
padding: .65rem 1rem;
border: 1px solid currentColor;
border-radius: 14px;
background: transparent;
cursor: pointer;
}Previewdesktop
HTMLCode
<form class="form-card" action="/submit" method="post">
<div class="field">
<label class="label" for="pref2">都道府県</label>
<select class="select" id="pref2" name="pref" required>
<option value="" disabled selected>選んでください</option>
<option value="tokyo">東京都</option>
<option value="osaka">大阪府</option>
</select>
</div>
<button class="btn" type="submit">送信</button>
</form>CSSCode
*{ box-sizing: border-box; }
.form-card{
max-width: 560px;
border: 1px solid rgba(0,0,0,.18);
border-radius: 18px;
padding: 1rem 1.1rem;
box-shadow: 0 10px 22px rgba(0,0,0,.08);
display: grid;
gap: .9rem;
}
.field{ display: grid; gap: .35rem; }
.label{ font-size: .95rem; }
.select{
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.25);
border-radius: 14px;
background: transparent;
}
.select:focus{
outline: 2px solid currentColor;
outline-offset: 2px;
}
.btn{
min-height: 44px;
padding: .65rem 1rem;
border: 1px solid currentColor;
border-radius: 14px;
background: transparent;
cursor: pointer;
}Preview を表示
理解チェック(3問・答え付き)
Q. 送信される値はoptionのどれ?(表示文字?value?)
A. value。
Q. 未選択を防ぐ定番のやり方は?
A. value="" disabled selected の「選んでください」option + required。
Q. 候補が少ないとき、selectより向くことが多いのは?
A. radio(全部見せられる)。
ミニ演習(すぐ試せる小課題 2つ)
-
「都道府県」をselectで作り、先頭に「選んでください」を置いてrequiredにしてください。
valueは英字(例:tokyo)にする。 -
候補が3つだけの「希望時間(午前/午後/指定なし)」を作り、
select版とradio版の両方を作って、どちらが選びやすいか比べてください。