23. inputの種類(checkbox / radio)
まず結論
複数選べるならcheckbox、1つだけ選ぶならradioを使うと、送信データもUIも自然になります。
最小の書き方(コピペで動く最小コード)
HTMLCode
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Checkbox & Radio</title>
</head>
<body>
<form action="/submit" method="post">
<p>参加したい曜日(複数OK)</p>
<input id="mon" name="days" type="checkbox" value="mon" />
<label for="mon">月</label>
<input id="wed" name="days" type="checkbox" value="wed" />
<label for="wed">水</label>
<p>支払い方法(1つだけ)</p>
<input id="pay-card" name="pay" type="radio" value="card" />
<label for="pay-card">カード</label>
<input id="pay-bank" name="pay" type="radio" value="bank" />
<label for="pay-bank">銀行振込</label>
<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>Checkbox & Radio</title>
</head>
<body>
<form action="/submit" method="post">
<p>参加したい曜日(複数OK)</p>
<input id="mon" name="days" type="checkbox" value="mon" />
<label for="mon">月</label>
<input id="wed" name="days" type="checkbox" value="wed" />
<label for="wed">水</label>
<p>支払い方法(1つだけ)</p>
<input id="pay-card" name="pay" type="radio" value="card" />
<label for="pay-card">カード</label>
<input id="pay-bank" name="pay" type="radio" value="bank" />
<label for="pay-bank">銀行振込</label>
<button type="submit">送信</button>
</form>
</body>
</html>
Preview を表示
重要ポイント(ここで迷いがち)
- checkbox(チェックボックス):複数選択OK
- 同じnameで複数に付ける → 選んだ分だけ送られる
- 何も選ばれない可能性がある(必須にするなら工夫が必要)
- radio(ラジオボタン):1つだけ選択
- 同じnameを共有すると「1つだけ」が成立
- nameが違うと“全部選べる”状態になって事故る
- valueが送信される中身
- 画面に見える文字(label)と送信値(value)は別
- 例:labelは「銀行振込」、valueはbank
- labelは必須級(小さい丸/四角を狙わなくて済む)
- label for と input id を紐付ける(#21)
例で理解(よく使うパターン 5つ)
1) 利用規約同意(checkbox 1個)
HTMLCode
<input id="agree" name="agree" type="checkbox" value="yes" required />
<label for="agree">利用規約に同意する</label>
Previewdesktop
HTMLCode
<input id="agree" name="agree" type="checkbox" value="yes" required />
<label for="agree">利用規約に同意する</label>
Preview を表示
checkboxでもrequiredは使えます(“チェック必須”にできる)。
2) 興味分野(checkbox 複数)
HTMLCode
<p>興味のある分野(複数可)</p>
<input id="tag-html" name="tags" type="checkbox" value="html" />
<label for="tag-html">HTML</label>
<input id="tag-css" name="tags" type="checkbox" value="css" />
<label for="tag-css">CSS</label>
<input id="tag-js" name="tags" type="checkbox" value="js" />
<label for="tag-js">JavaScript</label>
Previewdesktop
HTMLCode
<p>興味のある分野(複数可)</p>
<input id="tag-html" name="tags" type="checkbox" value="html" />
<label for="tag-html">HTML</label>
<input id="tag-css" name="tags" type="checkbox" value="css" />
<label for="tag-css">CSS</label>
<input id="tag-js" name="tags" type="checkbox" value="js" />
<label for="tag-js">JavaScript</label>
Preview を表示
3) 配送時間(radio 1つ)
HTMLCode
<p>配送時間</p>
<input id="t-am" name="time" type="radio" value="am" required />
<label for="t-am">午前</label>
<input id="t-pm" name="time" type="radio" value="pm" />
<label for="t-pm">午後</label>
Previewdesktop
HTMLCode
<p>配送時間</p>
<input id="t-am" name="time" type="radio" value="am" required />
<label for="t-am">午前</label>
<input id="t-pm" name="time" type="radio" value="pm" />
<label for="t-pm">午後</label>
Preview を表示
radioで必須にしたい場合、グループ内のどれか1つにrequiredを付けるのが一般的。
4) “既定で選ばれている”状態(checked)
HTMLCode
<input id="pay-card2" name="pay" type="radio" value="card" checked />
<label for="pay-card2">カード</label>
Previewdesktop
HTMLCode
<input id="pay-card2" name="pay" type="radio" value="card" checked />
<label for="pay-card2">カード</label>
Preview を表示
5) checkboxの初期ON(設定画面など)
HTMLCode
<input id="mail" name="notify_mail" type="checkbox" value="1" checked />
<label for="mail">メール通知を受け取る</label>
Previewdesktop
HTMLCode
<input id="mail" name="notify_mail" type="checkbox" value="1" checked />
<label for="mail">メール通知を受け取る</label>
Preview を表示
使い分け(超シンプルに)
- 複数OK → checkbox
- 1つだけ → radio
「はい/いいえ」でも、どっちが自然?
- “同意”などON/OFFならcheckboxが自然
- 2択の選択(例:個人/法人)ならradioが自然
実務のコツ(SEO/安全/アクセシビリティ)
- radio/checkboxは「選択肢のまとまり」を先に示す
例:支払い方法
のように“何の選択か”が分かると迷いにくい - valueはサーバーが扱いやすい値に
例:bank / card、mon / tue などブレない短い英字が無難 - クリック領域を広くする(CSSでlabelをブロック化)
スマホで誤タップが激減 - 必須は“見た目だけ”にしない
requiredを使う(エラー表示は次のテーマで拡張)
NG・禁止例(事故る書き方)
NG1)radioなのにnameがバラバラ(全部選べてしまう)
HTMLCode
<input type="radio" name="pay1" value="card" />
<input type="radio" name="pay2" value="bank" />
Previewdesktop
HTMLCode
<input type="radio" name="pay1" value="card" />
<input type="radio" name="pay2" value="bank" />
Preview を表示
✅ 正:同じnameに統一
HTMLCode
<input type="radio" name="pay" value="card" />
<input type="radio" name="pay" value="bank" />
Previewdesktop
HTMLCode
<input type="radio" name="pay" value="card" />
<input type="radio" name="pay" value="bank" />
Preview を表示
NG2)valueが無い/適当で後で困る
HTMLCode
<input id="pay" name="pay" type="radio" />
Previewdesktop
HTMLCode
<input id="pay" name="pay" type="radio" />
Preview を表示
✅ 正:valueを決める
HTMLCode
<input id="pay-card" name="pay" type="radio" value="card" />
Previewdesktop
HTMLCode
<input id="pay-card" name="pay" type="radio" value="card" />
Preview を表示
NG3)label無しで小さいクリック地獄
HTMLCode
<input type="checkbox" /> 利用規約に同意
Previewdesktop
HTMLCode
<input type="checkbox" /> 利用規約に同意
Preview を表示
✅ 正:labelで紐付け
HTMLCode
<input id="agree2" type="checkbox" />
<label for="agree2">利用規約に同意</label>
Previewdesktop
HTMLCode
<input id="agree2" type="checkbox" />
<label for="agree2">利用規約に同意</label>
Preview を表示
NG4)checkbox複数でidを使い回す(紐付けが壊れる)
HTMLCode
<input id="tag" type="checkbox" />
<input id="tag" type="checkbox" />
Previewdesktop
HTMLCode
<input id="tag" type="checkbox" />
<input id="tag" type="checkbox" />
Preview を表示
✅ 正:idはユニークに
見た目を整える(HTML+CSSセット:5例)
色は使わず、線・余白・影・押しやすさで整えます。
例1)選択肢を“押せる行”にする(おすすめ)
例1)選択肢を“押せる行”にする(おすすめ)
HTMLCode
<div class="group">
<p class="group__title">興味のある分野(複数可)</p>
<div class="choice">
<input class="choice__ctl" id="c1" name="tags" type="checkbox" value="html" />
<label class="choice__label" for="c1">HTML</label>
</div>
<div class="choice">
<input class="choice__ctl" id="c2" name="tags" type="checkbox" value="css" />
<label class="choice__label" for="c2">CSS</label>
</div>
<div class="choice">
<input class="choice__ctl" id="c3" name="tags" type="checkbox" value="js" />
<label class="choice__label" for="c3">JavaScript</label>
</div>
</div>CSSCode
.group{ max-width: 560px; }
.group__title{ margin: 0 0 .6rem; font-weight: 600; }
.choice{
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
box-shadow: 0 10px 22px rgba(0,0,0,.06);
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }
.choice:has(.choice__ctl:focus-visible){
outline: 3px solid currentColor;
outline-offset: 3px;
}Previewdesktop
HTMLCode
<div class="group">
<p class="group__title">興味のある分野(複数可)</p>
<div class="choice">
<input class="choice__ctl" id="c1" name="tags" type="checkbox" value="html" />
<label class="choice__label" for="c1">HTML</label>
</div>
<div class="choice">
<input class="choice__ctl" id="c2" name="tags" type="checkbox" value="css" />
<label class="choice__label" for="c2">CSS</label>
</div>
<div class="choice">
<input class="choice__ctl" id="c3" name="tags" type="checkbox" value="js" />
<label class="choice__label" for="c3">JavaScript</label>
</div>
</div>CSSCode
.group{ max-width: 560px; }
.group__title{ margin: 0 0 .6rem; font-weight: 600; }
.choice{
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
box-shadow: 0 10px 22px rgba(0,0,0,.06);
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }
.choice:has(.choice__ctl:focus-visible){
outline: 3px solid currentColor;
outline-offset: 3px;
}Preview を表示
例2)横並び(タグっぽい)※見た目だけ軽く
例2)横並び(タグっぽい)※見た目だけ軽く
HTMLCode
<div class="chips" aria-label="興味のある分野(複数可)">
<input id="t1" name="tags" type="checkbox" value="html" />
<label for="t1" class="chip">HTML</label>
<input id="t2" name="tags" type="checkbox" value="css" />
<label for="t2" class="chip">CSS</label>
<input id="t3" name="tags" type="checkbox" value="js" />
<label for="t3" class="chip">JavaScript</label>
</div>CSSCode
.chips{ display: flex; gap: .5rem; flex-wrap: wrap; }
.chips input{
position: absolute;
opacity: 0;
pointer-events: none;
}
.chip{
display: inline-block;
padding: .5rem .85rem;
border: 1px solid rgba(0,0,0,.2);
border-radius: 999px;
cursor: pointer;
user-select: none;
transition: transform .15s ease, box-shadow .15s ease;
}
.chips input:focus-visible + .chip{
outline: 3px solid currentColor;
outline-offset: 3px;
}
.chips input:checked + .chip{
box-shadow: 0 10px 22px rgba(0,0,0,.10);
transform: translateY(-1px);
}Previewdesktop
HTMLCode
<div class="chips" aria-label="興味のある分野(複数可)">
<input id="t1" name="tags" type="checkbox" value="html" />
<label for="t1" class="chip">HTML</label>
<input id="t2" name="tags" type="checkbox" value="css" />
<label for="t2" class="chip">CSS</label>
<input id="t3" name="tags" type="checkbox" value="js" />
<label for="t3" class="chip">JavaScript</label>
</div>CSSCode
.chips{ display: flex; gap: .5rem; flex-wrap: wrap; }
.chips input{
position: absolute;
opacity: 0;
pointer-events: none;
}
.chip{
display: inline-block;
padding: .5rem .85rem;
border: 1px solid rgba(0,0,0,.2);
border-radius: 999px;
cursor: pointer;
user-select: none;
transition: transform .15s ease, box-shadow .15s ease;
}
.chips input:focus-visible + .chip{
outline: 3px solid currentColor;
outline-offset: 3px;
}
.chips input:checked + .chip{
box-shadow: 0 10px 22px rgba(0,0,0,.10);
transform: translateY(-1px);
}Preview を表示
例3)ラジオを縦に揃える(グループっぽく)
例3)ラジオを縦に揃える(グループっぽく)
HTMLCode
<div class="group">
<p class="group__title">支払い方法(1つだけ)</p>
<div class="choice">
<input class="choice__ctl" id="r1" name="pay" type="radio" value="card" required />
<label class="choice__label" for="r1">カード</label>
</div>
<div class="choice">
<input class="choice__ctl" id="r2" name="pay" type="radio" value="bank" />
<label class="choice__label" for="r2">銀行振込</label>
</div>
<div class="choice">
<input class="choice__ctl" id="r3" name="pay" type="radio" value="cash" />
<label class="choice__label" for="r3">代引き</label>
</div>
</div>CSSCode
.group{ max-width: 560px; }
.group__title{ margin: 0 0 .6rem; font-weight: 600; }
.choice{
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }
.choice:has(.choice__ctl:focus-visible){
outline: 3px solid currentColor;
outline-offset: 3px;
border-radius: 18px;
}Previewdesktop
HTMLCode
<div class="group">
<p class="group__title">支払い方法(1つだけ)</p>
<div class="choice">
<input class="choice__ctl" id="r1" name="pay" type="radio" value="card" required />
<label class="choice__label" for="r1">カード</label>
</div>
<div class="choice">
<input class="choice__ctl" id="r2" name="pay" type="radio" value="bank" />
<label class="choice__label" for="r2">銀行振込</label>
</div>
<div class="choice">
<input class="choice__ctl" id="r3" name="pay" type="radio" value="cash" />
<label class="choice__label" for="r3">代引き</label>
</div>
</div>CSSCode
.group{ max-width: 560px; }
.group__title{ margin: 0 0 .6rem; font-weight: 600; }
.choice{
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }
.choice:has(.choice__ctl:focus-visible){
outline: 3px solid currentColor;
outline-offset: 3px;
border-radius: 18px;
}Preview を表示
例4)“必須”の見せ方(見た目はラベル、実際はrequired)
例4)“必須”の見せ方(見た目はラベル、実際はrequired)
HTMLCode
<div class="group">
<p class="group__title">
連絡方法 <span class="req" aria-hidden="true">必須</span>
</p>
<div class="choice">
<input class="choice__ctl" id="m1" name="contact_method" type="radio" value="email" required />
<label class="choice__label" for="m1">メール</label>
</div>
<div class="choice">
<input class="choice__ctl" id="m2" name="contact_method" type="radio" value="tel" />
<label class="choice__label" for="m2">電話</label>
</div>
</div>CSSCode
.group{ max-width: 560px; }
.group__title{ margin: 0 0 .6rem; font-weight: 600; }
.req{
display: inline-block;
padding: .1rem .45rem;
border: 1px solid currentColor;
border-radius: 999px;
font-size: .8rem;
opacity: .8;
margin-left: .4rem;
}
.choice{
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }Previewdesktop
HTMLCode
<div class="group">
<p class="group__title">
連絡方法 <span class="req" aria-hidden="true">必須</span>
</p>
<div class="choice">
<input class="choice__ctl" id="m1" name="contact_method" type="radio" value="email" required />
<label class="choice__label" for="m1">メール</label>
</div>
<div class="choice">
<input class="choice__ctl" id="m2" name="contact_method" type="radio" value="tel" />
<label class="choice__label" for="m2">電話</label>
</div>
</div>CSSCode
.group{ max-width: 560px; }
.group__title{ margin: 0 0 .6rem; font-weight: 600; }
.req{
display: inline-block;
padding: .1rem .45rem;
border: 1px solid currentColor;
border-radius: 999px;
font-size: .8rem;
opacity: .8;
margin-left: .4rem;
}
.choice{
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }Preview を表示
例5)フォーカスが分かる(キーボード操作)
例5)フォーカスが分かる(キーボード操作)
HTMLCode
<div class="choice">
<input class="choice__ctl" id="f1" name="days" type="checkbox" value="fri" />
<label class="choice__label" for="f1">金</label>
</div>
<div class="choice">
<input class="choice__ctl" id="f2" name="days" type="checkbox" value="sat" />
<label class="choice__label" for="f2">土</label>
</div>CSSCode
.choice{
max-width: 560px;
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }
.choice__ctl:focus-visible{
outline: 3px solid currentColor;
outline-offset: 3px;
border-radius: 6px;
}Previewdesktop
HTMLCode
<div class="choice">
<input class="choice__ctl" id="f1" name="days" type="checkbox" value="fri" />
<label class="choice__label" for="f1">金</label>
</div>
<div class="choice">
<input class="choice__ctl" id="f2" name="days" type="checkbox" value="sat" />
<label class="choice__label" for="f2">土</label>
</div>CSSCode
.choice{
max-width: 560px;
display: flex;
gap: .7rem;
align-items: center;
padding: .75rem .9rem;
border: 1px solid rgba(0,0,0,.18);
border-radius: 16px;
margin: .5rem 0;
}
.choice__ctl{ width: 18px; height: 18px; }
.choice__label{ cursor: pointer; line-height: 1.6; flex: 1; }
.choice__ctl:focus-visible{
outline: 3px solid currentColor;
outline-offset: 3px;
border-radius: 6px;
}Preview を表示
理解チェック(3問・答え付き)
Q. 複数選択できる入力はどっち?
A. checkbox。
Q. radioで「1つだけ選べる」条件は何?
A. 同じnameを共有していること。
Q. 送信される値を決めるのはラベル(表示文字)?それとも?
A. value(送信される中身)。
ミニ演習(すぐ試せる小課題 2つ)
-
「興味のある分野(HTML/CSS/JS)」をcheckboxで作り、
それぞれに value="html" 等を付けてください。CSS例1で“押せる行”に。 -
「連絡方法(メール/電話)」をradioで作り、
同じname(例:contact_method)にして1つだけ選べることを確認。
片方をcheckedにして初期選択も試してください。