- 技術 💻
ラジオボタンとは|チェックボックスとの違い・HTMLの作り方・CSSの変え方
結論
ラジオボタンは、複数の選択肢から「1つだけ」を選ぶための部品です。HTML では <input type="radio"> に同じ name を付けたものが1つのグループになり、どれかを選ぶと他が自動で外れ、送信されるのは選んだ1つの name=value だけです。
この記事でわかること
- チェックボックス・セレクト・トグルとの違いと、どれを使うかの判断表
- name のグループ化・label のクリック範囲・矢印キーの動き・送信値の原文(Chromium と自作サーバーで実測)
- CSS で見た目を変える3通り(accent-color・appearance:none・画像)と、アクセシビリティの確認結果
ラジオボタンの「ラジオ」は、以前のカーラジオの選局ボタンに由来します。1つを押し込むと、それまで押されていたボタンが飛び出して戻る仕組みで、「同時に1つしか選べない」という性質がそのまま名前になりました。
flowchart TD
Q{いくつ選ぶ?} -->|複数| C[チェックボックス]
Q -->|1つだけ| N{選択肢の数}
N -->|2〜7つ| R[ラジオボタン]
N -->|多い| S[セレクト]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| ラジオボタンとは | 複数の選択肢から1つだけ選ぶ丸い部品。選ぶと他が外れる | ラジオボタンとは |
| チェックボックスとの違い | ラジオは1つだけ・解除できない。チェックは0個以上・個別に外せる | チェックボックスとの違い |
| HTML の書き方 | <input type="radio" name="…" value="…"> と <label> |
HTMLでの作り方 |
| グループにならない | name が違う(大文字小文字も区別) |
nameでグループになる |
| 送られる値 | 選んだ1つの name=value だけ。value が無いと on |
送信で届く値の原文 |
| 見た目を変えたい | accent-color(色だけ)・appearance:none(自作)・画像 | CSSで見た目を変える3通り |
| 選択を解除したい | 仕様上できない。「選ばない」という選択肢を足す | 選択を解除できない仕様 |
| キーボードで選ぶ | Tab でグループに入り、矢印キーで移動と選択が同時に起きる | キーボード操作 |
確認環境:Ubuntu 24.04.5 LTS の上で、Python 3.13.18 の http.server を使った自作サーバー(フォームの送信を受け取り、本文をそのまま記録する)を 127.0.0.1 のポートに起動し、ラジオボタンを並べたページを置きました。ブラウザの動き(グループ化・label のクリック範囲・キーボード操作・JavaScript での取得と変更・送信・CSS の描画とアクセシビリティツリー)は Chromium 153.0.8010.12(Playwright 1.63.0)で操作し、スクリーンショットの画素の色と要素の座標を数値で記録しました。仕様の記述は HTML Living Standard と MDN、キーボード操作の決まりは WAI-ARIA Authoring Practices Guide、React と Vue の書き方は各公式ドキュメントで確かめました。図は mermaid で描画を確かめています(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ラジオボタンとは|チェックボックスとの違い・HTMLの作り方・CSSの変え方」
ラジオボタンとは(意味・見た目・使われる場面)
この節では、ラジオボタンが何をする部品で、どこで使われているのかが分かります。
ラジオボタンは、互いに排他的な選択肢の中から1つだけを選ばせる入力部品です。 丸い印で表示され、未選択は白抜き、選択すると中に点が入ります。HTML Living Standard では <input> 要素の「Radio Button state」として定義され、MDN は「ラジオグループと呼ばれる関連する選択肢の集まりを表し、同時に選べるのはグループ内の1つだけ」と説明しています。
1支払い方法・配送方法
「クレジットカード/コンビニ払い/代引き」のように、必ず1つに決める項目。
2はい・いいえの質問
アンケートの「はい/いいえ/どちらとも言えない」。全部の選択肢を一目で見せたいときに向く。
3OS・アプリの設定画面
印刷の「片面/両面」、保存形式、ネットワークの接続方法など。Windows・Mac・スマホの設定画面にも同じ部品がある。
この記事は Web ページ(HTML)のラジオボタンを中心に扱いますが、「1つだけ選ぶ・選ぶと他が外れる・自分では解除できない」という性質は、OS やアプリの画面でも同じです。
灰色で選べないラジオボタン
設定画面で丸が灰色になっていて押せないのは、「今は変更できない」状態(HTML では disabled)です。別の設定が前提になっている、管理者の権限が要る、読み込みが終わっていない、といった理由で無効になっています。手元の Chromium でも、disabled のラジオボタンはクリックしても選べず、Tab と矢印キーも飛ばしました。押せない項目があるときは、不具合と決めつける前に、同じ画面の説明文と前提の設定を見ます。
ラジオボタンとチェックボックスの違い
この節では、いちばん混同されやすいチェックボックスとの違いと、見分ける問いが分かります。
違いは「いくつ選べるか」と「自分で外せるか」の2点です。 手元の Chromium で、選んだあとにもう一度クリックしたときの結果も含めて並べます。
| ラジオボタン | チェックボックス | |
|---|---|---|
| 形 | 丸(選ぶと中に点) | 四角(選ぶとチェックマーク) |
| 選べる数 | グループの中で1つだけ | 0個から全部まで |
| 別の項目を選ぶと | 前の選択が自動で外れる | 前の選択はそのまま残る |
| 選択中の項目をもう一度クリック | 外れない(手元で確認:checked は true のまま) | 外れる |
| HTML | <input type="radio">(同じ name で1組) |
<input type="checkbox">(1つずつ独立) |
| 向く質問 | 「どれか1つ」「はい/いいえ」 | 「あてはまるものすべて」「同意する」 |
質問の文で決める
見分ける問い:「2つ以上あてはまることがあるか」。あるならチェックボックス
「性別」「年代」のように1つに決まる項目はラジオ、「受け取りたいお知らせの種類」のように複数あり得る項目はチェックボックスです。選択肢が1つしかない「同意する」は、オン/オフの2状態なのでチェックボックスを使います(ラジオボタンは1つだけ置くと外せなくなります)。
HTMLでの作り方(name・value・id・label)
この節では、ラジオボタンの基本の書き方と、4つの属性がそれぞれ何を決めるのかが分かります。
1つのラジオボタンは <input type="radio"> と、その文字を書く <label> の組で作ります。 手元で使ったフォームの中心の部分です。
<form action="/submit" method="post">
<fieldset>
<legend>連絡方法(必須)</legend>
<input type="radio" id="c1" name="contact" value="email" required>
<label for="c1">メール</label>
<input type="radio" id="c2" name="contact" value="phone">
<label for="c2">電話</label>
<input type="radio" id="c3" name="contact" value="fax" disabled>
<label for="c3">FAX(受付停止中)</label>
</fieldset>
<fieldset>
<legend>配送(任意)</legend>
<label><input type="radio" name="ship" value="normal" checked> 通常</label>
<label><input type="radio" name="ship" value="express"> 速達</label>
<label><input type="radio" name="ship" value="none"> 配送なし</label>
</fieldset>
<button type="submit">送信</button>
</form>
| 属性 | 役割 | 無いとどうなる(手元で確認) |
|---|---|---|
name |
グループの名前。同じ name が1組になり、送信時のキーになる | グループにならず、全部を同時に選べる。送信にも含まれない |
value |
選んだときにサーバーへ送られる値。画面には出ない | 値が on になる(agree=on のように届く) |
id と label for |
文字をクリックしても選べるようにし、読み上げの名前になる | 文字をクリックしても選べず、読み上げは名前の無い「radio」になる |
checked |
最初から選んでおく | 何も選ばれていない状態で始まる |
required |
グループのどれか1つを選ばないと送信できない(1つに付ければグループ全体に効く) | 未選択のまま送信できる(そのグループは送られない) |
disabled |
選べなくする。選択済みでも送信されない | ― |
<fieldset> と <legend> は、グループの見出しです。手元のアクセシビリティツリーでは group "連絡方法(必須)" の中に3つの radio が入り、読み上げソフトにも「何についての選択肢か」が伝わる形になりました。label は for で結ぶ形と、input を中に包む形のどちらでも動きます(クリック範囲の違いは後の節)。
nameでグループになる仕組み(Chromiumで確認)
この節では、「同じ name=1つのグループ」の決まりと、グループにならない原因が分かります。
ラジオボタンのグループは、同じフォームの中で同じ name を持つものです。 手元で確かめた結果です。
初期 checked: contact=email:false contact=phone:false contact=fax:false ship=normal:true ...
電話クリック後: email:false phone:true fax:false
メールクリック後: email:true phone:false fax:false
メールをもう一度クリック: True ← 外れない
name違い両方(size1/size2): size1:true size2:true ← 別グループなので両方選べる
disabled クリック: False ← 選べない
checked が2つ(dup a/b): dup=a:false dup=b:true ← 後に書いたほうが有効
| 状況 | 結果(Chromium 153) |
|---|---|
| 同じ form の中で同じ name | 1つのグループ。1つ選ぶと他が外れる |
別の <form> に同じ name |
別のグループ。片方を選んでももう片方は変わらない |
| form の外に置いた同じ name | form の外どうしで1つのグループになる(form の中とは別) |
name が h と H |
別のグループ(大文字小文字を区別する)。両方選べた |
checked を2つに書いた |
後に書いたほう(b)だけが選ばれる |
「クリックしても他が外れない」「2つ同時に選べてしまう」ときは、まず name の綴りを見ます。name="contact" と name="contacts"、半角と全角の違いでも別のグループになります。
labelのクリック範囲(座標で実測)
この節では、文字をクリックしても選べるようにする label の2つの書き方と、クリックできる範囲の違いが数値で分かります。
既定のラジオボタンは 13px × 13px しかありません。 label を結ぶと、文字の部分もクリックできるようになり、スマートフォンでも押しやすくなります。手元で要素の座標を取った結果です。
input c1(既定の丸) : x=41 y=50 幅13 高さ13 (13×13 = 169 px²)
label for=c1「メール」 : x=57 y=49 幅48.8 高さ17 (48.8×17 ≈ 829 px²)
label で包んだ「速達」 : x=98 y=109 幅57.5 高さ17 (丸+隙間+文字が1つの範囲)
| クリックした場所 | for で結んだ label | input を包んだ label |
|---|---|---|
| 丸の中 | 選べる | 選べる |
| 文字の上 | 選べる(「電話」クリック → checked true) | 選べる |
| 丸と文字の隙間(x=55.5) | 選べない(input の右端 54 と label の左端 57 の間) | 選べる(label の範囲の中) |
| label の無い文字 | 選べない(「ラベル無しの文字」クリック → false) | ― |
for で結ぶ(id が要る)
input と文字を別の場所に置ける
丸と文字の間に押せない隙間ができる
React では id の重複に注意(useId)
label で包む(id が不要)
丸から文字まで切れ目なく押せる
label に padding を付ければ範囲をさらに広げられる
一覧で並べるフォームに向く
クリックできる面積は、丸だけの 169px² に対し、文字を含めると 5倍近くになりました。どちらの書き方でも、label を付けないラジオボタンは作らないのが基本です。
WCAG 2.2 の達成基準 2.5.8「ターゲットのサイズ(最低限)」(レベル AA)は、押す対象を 24×24 CSS ピクセル以上にするか、隣の対象と間隔を空けることを求めています(ブラウザが決めた大きさをそのまま使う場合などの例外あり)。既定の丸は 13px で、この目安の半分ほどしかありません。label を結んで文字まで押せるようにし、縦に並べるときは項目の間に余白(label の padding や margin)を取ると、指でも押し分けやすくなります。
キーボード操作(Tab・矢印キー・Space・Enter)
この節では、マウスを使わずにラジオボタンを選ぶときの動きが、実際の操作ログで分かります。
Tab はグループに1回だけ止まり、矢印キーで「移動と選択」が同時に起きます。 WAI-ARIA Authoring Practices Guide(APG)が定める動きで、Chromium の既定の <input type="radio"> もそのとおりに動きました。
Tab 1回目: *email phone fax normal✓ express none ← 未選択のグループは先頭に止まる
↓ : email *phone✓ fax ... ← 移動と同時に選択
↓ : *email✓ phone fax ... ← disabled の fax を飛ばして先頭へ戻る
→ : email *phone✓ fax ...
↑ : *email✓ phone fax ...
Tab 2回目: email✓ phone fax *normal✓ express none ← 次のグループは checked の項目に止まる
Shift+Tab: *email✓ phone fax normal✓ ...
Space(未選択の電話にフォーカス): phone✓ ← 選ぶ
Space もう一度: phone✓ ← 外れない
Enter : /submit へ送信された(contact=phone&ship=normal&dup=b)
Tab の止まる順(全体): c1 → normal → on → S → M → b ← グループごとに1回
| キー | 動き(APG の決まり) | 手元の結果 |
|---|---|---|
| Tab / Shift+Tab | グループに入る・出る。選択済みがあればそこに、無ければ先頭に止まる | 同じ(disabled は止まらない) |
| ↓ / → | 次へ移動し、同時に選択する。末尾からは先頭へ戻る | 同じ(disabled を飛ばした) |
| ↑ / ← | 前へ移動し、同時に選択する。先頭からは末尾へ戻る | 同じ |
| Space | 未選択なら選択する | 同じ。選択済みに押しても外れない |
| Enter | (APG の対象外) | フォームが送信された |
「矢印キーを押しただけで選択が変わる」のは仕様どおりの動きです。選択が変わるたびに画面を切り替える(ページを移動する・大きく描き直す)作りにすると、キーボードで次の項目を見に行くだけで切り替わってしまうため、確定はボタンで行います。
フォーム送信で届く値の原文(自作サーバーで受信)
この節では、ラジオボタンを送信したときにサーバーに何が届くのかが、記録した原文で分かります。
届くのは、グループごとに「選んだ1つの name=value」だけです。 自作サーバーが受け取った本文をそのまま載せます。
POST /submit Content-Type: application/x-www-form-urlencoded Content-Length: 47
contact=email&ship=normal&size1=S&size2=M&dup=b
(contact を未選択・FAX を disabled のまま checked にして送信)
POST /submit Content-Length: 18
ship=express&dup=b ← 未選択のグループと disabled は届かない
(method="get" にして送信)
GET /submit?contact=phone&ship=normal&dup=b
(value="電話" にして送信)
contact=%E9%9B%BB%E8%A9%B1&ship=normal&dup=b ← 日本語は UTF-8 のパーセント符号化
(value 属性を書かずに選択して送信)
agree=on ← 既定の値は on
enctype="multipart/form-data"(ファイルを一緒に送るフォーム)では、同じ値が次の形で届きました。
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryZZgfn6h9Iolyh99X
------WebKitFormBoundaryZZgfn6h9Iolyh99X
Content-Disposition: form-data; name="contact"
phone
------WebKitFormBoundaryZZgfn6h9Iolyh99X
Content-Disposition: form-data; name="ship"
normal
------WebKitFormBoundaryZZgfn6h9Iolyh99X--
- 1未選択のグループは「空文字」ではなく「無い」サーバー側で
contactを取ると None / undefined になる。必須なら required とサーバーの両方で確かめる - 2value を忘れると全部 on になるどれを選んでも
onが届き、区別できない。value は必ず書く - 3disabled は届かない「受付停止中」のように見せたいだけなら disabled、値は送りたいなら別の方法(readonly はラジオには効かない。手元で確認)
- 4届いた値は選択肢の中にあるか確かめるvalue は開発者ツールで書き換えられる。サーバーでは許可した値の一覧と照合する
PHP や Python でフォームの値を受け取る一般的な書き方は、関連記事「PHPフォームのPOST受け取り方 $_POSTとエスケープ・入力チェック」で扱っています。
required・checked・disabledの挙動
この節では、必須・初期値・無効の3つの属性が、検証と送信にどう効くのかが分かります。
required はグループの中の1つに付ければ、グループ全体が「どれか1つ必須」になります。 MDN も「属性を付けたボタン自体を選ぶ必要はない」と説明しています。手元の結果です。
checkValidity(未選択): False
validity.valueMissing c1(required あり)=true c2(required なし)=true ← グループ全体が未選択扱い
validationMessage(英語の画面): Please select one of these options.
c2(required の無いほう)を選んだ後: c1.valueMissing=false form.checkValidity()=true
required
未選択で送信すると、ブラウザが送信を止めて選択を促す文言を出す。valueMissing はグループの全員が true になる。
1つに付ければ全体に効く
checked
初期値。2つに書くと後のほうが勝つ。JavaScript で checked=true にしても属性は変わらず、form.reset() で属性どおりに戻る(手元で確認)。
defaultChecked が属性の値
disabled
クリックしても選べず、Tab も矢印キーも飛ばす。JavaScript で checked にしても送信されない。
「今は選べない」を示す
Firefox は、ページを再読み込みしても直前の選択を保持することがあります(MDN)。初期値を必ず HTML どおりにしたいときは autocomplete="off" を付けます。required・pattern など検証全体の書き方は、関連記事「HTMLフォームバリデーション|required・pattern早見表と完成例」で扱っています。
JavaScriptで選択値を取得・変更する
この節では、JavaScript で「今どれが選ばれているか」を取り、別の項目を選ばせる3つの書き方が分かります。
いちばん短いのは form.elements.contact.value です。 同じ name のラジオボタンは RadioNodeList という特別なリストになり、value で選択値の取得と変更の両方ができます。
const form = document.getElementById('f');
// 取得(3通り)
document.querySelector('input[name="contact"]:checked')?.value; // 'email'(未選択なら undefined)
form.elements.contact.value; // 'email'(未選択なら '')
new FormData(form).get('contact'); // 'email'(未選択なら null)
// 変更
form.elements.contact.value = 'phone'; // value が phone の項目を選ぶ
document.getElementById('c1').checked = true; // 直接 checked にする(他は自動で外れる)
// 変わったことを受け取る
for (const r of form.elements.contact) {
r.addEventListener('change', e => console.log('選択:', e.target.value));
}
RadioNodeList length=3
JS 取得 :checked = email / form.elements.contact.value = email
FormData: contact=email&ship=normal&size1=S&size2=M&dup=b
value='phone' を代入 → email:false phone:true fax:false
value='zzz'(無い値)を代入 → 何も変わらない(phone のまま)
c1.checked=true → email:true phone:false fax:false
全部 checked=false → form.elements.contact.value は ''、:checked は null
イベントの順: click → input → change(いずれも checked=true の状態で発火)
changeは「選ばれた側」でだけ発火します。外れた側では発火しないので、「どれが外れたか」を知りたいときは直前の値を自分で持っておきます。- JavaScript で全部
checked=falseにすると「選択なし」の状態を作れます。ただし利用者はその状態に戻せないので、初期化(リセット)の用途に限ります。
select・checkbox も含めた値の取得と設定の書き方は、関連記事「HTML select・checkbox・radioの書き方|初期値と値取得」で扱っています。
CSSで見た目を変える3通り(accent-color・appearance:none・画像)
この節では、ラジオボタンの色や大きさを変える3つの方法と、それぞれで何が変わり何が残るのかが、実測の結果で分かります。
色を変えるだけなら accent-color、形から作るなら appearance: none、デザインデータの画像を使うなら「input を隠して label に描く」方法です。 同じページに4つの書き方を並べて、Chromium で描画・操作しました。
/* 1. accent-color:色だけ変える(いちばん手軽) */
.acc input { accent-color: #0b57d0; width: 20px; height: 20px; }
/* 2. appearance:none:既定の見た目を消して自分で描く */
.app input {
appearance: none; width: 20px; height: 20px; margin: 0;
border: 2px solid #767676; border-radius: 50%;
display: inline-grid; place-content: center; background: #fff;
}
.app input::before {
content: ""; width: 10px; height: 10px; border-radius: 50%;
background: #0b57d0; transform: scale(0); transition: transform .12s;
}
.app input:checked { border-color: #0b57d0; }
.app input:checked::before { transform: scale(1); }
.app input:focus-visible { outline: 2px solid #0b57d0; outline-offset: 2px; }
/* 3. 画像:input は見えなくする(消さない)。label の ::before に画像を出す */
.img input {
position: absolute; width: 1px; height: 1px; margin: -1px;
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.img label::before { content: ""; width: 20px; height: 20px; background: url(radio-off.svg) center/20px no-repeat; }
.img input:checked + label::before { background-image: url(radio-on.svg); }
.img input:focus-visible + label::before { outline: 2px solid #0b57d0; outline-offset: 2px; }
| 方法 | 描画された大きさ | 選択時の中心の色(画素) | Tab で止まる | 読み上げ(role) |
|---|---|---|---|---|
| 0 既定 | 13×13 | rgb(0,117,255)(Chromium の既定色) | 止まる | radio "A" [checked] |
| 1 accent-color | 20×20 | rgb(11,87,208)=指定した色 | 止まる | radio "A" [checked] |
| 2 appearance:none | 20×20 | rgb(11,87,208) | 止まる | radio "A" [checked] |
| 3 画像(input は 1×1 に隠す) | label の ::before が 20×20 | rgb(11,87,208) | 止まる | radio "A" [checked] |
| × input を display:none | (描画されない) | ― | 止まらない | radio が消える(文字 "● A ○ B" だけ) |
どの方法を選ぶか
| 方法 | できること | 向く場面 |
|---|---|---|
| accent-color | 選択時の色と(width/height で)大きさ。形は OS の既定のまま | ブランドの色に合わせるだけでよい。CSS 1行で済ませたい |
| appearance:none | 枠・中の点・アニメーション・ホバーまで自由。フォーカスの輪は自分で書く | デザインが決まっている。OS ごとの見た目の差を無くしたい |
| 画像(input を隠す) | SVG や PNG をそのまま使える。input の機能は残る | デザインデータの画像をそのまま使う。アイコン型の選択肢 |
いずれの方法でも、手元では 2つ目の label をクリックすると2つ目が選ばれ、矢印キーでも移動できました。見た目を変えても input 自体を残しているためです。フォーム全体の装飾(input・select・ボタン・エラー表示)は、関連記事「CSSフォームデザイン|input・select・チェックボックス装飾」で扱っています。
見た目を変えたあとのアクセシビリティ確認
この節では、CSS で見た目を変えたラジオボタンが、キーボードと読み上げソフトで使えるかを確かめる4つの点が分かります。
確かめるのは「Tab で止まるか」「フォーカスの輪が見えるか」「読み上げに radio と名前が残るか」「コントラスト比」の4つです。 手元の結果です。
[既定] Tabで止まる=yes focus-visible=True 輪の画素 focus=(16,16,16) blur=(255,255,255) 輪が見える=True
[accent-color] Tabで止まる=yes focus-visible=True 輪が見える=True
[appearance:none] Tabで止まる=yes focus-visible=True 輪の画素 focus=(11,87,208) 輪が見える=True ← 自分で書いた outline
[画像] Tabで止まる=yes focus-visible=True 輪が見える=True ← label::before に outline
[display:none] Tabで止まらない 輪が見える=False a11y: group "x display:none": x display:none ● A ○ B
input を display:none・visibility:hidden にしない
Tab で止まらず、アクセシビリティツリーから radio が消える。隠すなら 1×1 に縮めて clip で切る(上の .img の書き方)か、opacity:0 で重ねる。
appearance:none にしたら :focus-visible を書く
既定のフォーカスの輪も一緒に消える。outline を自分で書く。マウスのクリックでは出ず、キーボードのときだけ出るのが :focus-visible。
枠線と選択色のコントラスト比を 3:1 以上にする
WCAG 2.2 の「非テキストのコントラスト」は 3:1。手元の #767676 は 4.54:1、#0b57d0 は 6.39:1。薄い灰色 #ccc は 1.61:1 で足りない。
読み上げの名前を確かめる
Chrome の開発者ツール「アクセシビリティ」で、各項目が radio で、label の文字が名前になっているかを見る。label の無い項目は名前の無い radio になる(手元で確認)。
span や div に role="radio" を付けて自作しない
見た目を自由にしたいからと、<input> を使わずに <span role="radio" tabindex="0"> で作ると、読み上げの名前は付いても、動きは何も付いてきません。JavaScript を書かずに置いたものを手元で操作した結果です。
Tab の止まる順: a → b → c → btn ← グループで1回ではなく、項目ごとに止まる
↓ : *通常✓ 速達 なし ← 移動しない
Space: 通常✓ *速達 なし ← 選ばれない(aria-checked は true にならない)
クリック: 通常✓ *速達 なし ← 選ばれない
a11y: radiogroup "配送" / radio "通常" [checked] / radio "速達" / radio "なし"
アクセシビリティツリーの上では radio に見えるのに、矢印キーも Space もクリックも効かない部品になります。APG のとおりに動かすには、矢印キーでの移動と選択・Tab の止まり方・aria-checked の更新をすべて JavaScript で書くことになります。<input type="radio"> を残して CSS で見た目だけ変えれば、この全部が最初から付いてきます。
選択を解除できない仕様と「選択なし」を許す設計
この節では、一度選ぶと自分では外せないラジオボタンで、任意の質問をどう作るかが分かります。
ラジオボタンは、選択済みの項目をもう一度クリックしても外れません。 手元でも、クリック・Space のどちらでも checked は true のままでした。任意の質問をラジオボタンで作ると、一度触った人は「何も答えない」状態に戻れなくなります。
任意の質問をラジオボタンで作るとき
デジタル庁デザインシステムも、任意項目には無選択を表す選択肢を用意するよう案内している
初期値(checked)を置くかどうか
| 場面 | 初期値 | 理由 |
|---|---|---|
| 多くの人が同じ答えになる設定(配送:通常) | 置く | 操作が1回減る。後から変えられる |
| 本人の意思を確かめる質問(同意・年代・支払い方法) | 置かない+required | 見落としたまま送られるのを防ぐ |
| 任意の質問 | 「指定しない」を置いて checked | 無選択の状態を選択肢として表す |
ラジオボタン・チェックボックス・セレクト・トグルの判断表
この節では、似た4つの部品のどれを使うかを、選ぶ数・選択肢の数・場面から決められます。
決め手は「選ぶ数」「選択肢の数」「選んだ瞬間に反映するか」の3つです。
- 12つ以上あてはまることがある → チェックボックス「あてはまるものすべて」。1つだけでも「同意する」のようなオン/オフはチェックボックス
- 2選んだ瞬間に効果が出る設定 → トグルスイッチ通知のオン/オフ、ダークモード。送信ボタンを押さずに反映する
- 31つだけ・選択肢が2〜7つ程度 → ラジオボタン全部の選択肢を一目で比べられる。説明文を添えやすい
- 41つだけ・選択肢が多い、場所が無い → セレクト都道府県・生まれ年。開くまで中身が見えないので、比べて選ぶ項目には向かない
| 部品 | 選ぶ数 | HTML | 向く選択肢の数 |
|---|---|---|---|
| ラジオボタン | 1つ(解除不可) | input type="radio" |
2〜7つ程度 |
| チェックボックス | 0個以上 | input type="checkbox" |
1つ〜十数個 |
| セレクト(プルダウン) | 1つ(multiple で複数) | select+option |
8つ以上・場所が狭い |
| トグルスイッチ | オン/オフ | input type="checkbox" role="switch" |
1つ(即時反映) |
ラジオボタンと同じ「1つだけ」を選ばせる部品でも、セレクトは選択肢を隠すため、支払い方法のように説明を見比べて決める項目ではラジオボタンが向きます。input の種類ごとの違いは、関連記事「HTML input type 一覧|全22種の用途・値の形式・検証結果の早見表」で扱っています。
ReactとVueでのラジオボタンの扱い
この節では、React と Vue でラジオボタンの選択値を状態と結びつける最小の書き方が分かります。
どちらも「グループの選択値を1つの変数で持つ」形です。 React は checked と onChange を各項目に書き、Vue は v-model を同じ変数に結びます(各公式ドキュメントの書き方)。
// React:選択値を state で持つ
const [contact, setContact] = useState('email');
const options = [['email', 'メール'], ['phone', '電話']];
return options.map(([v, label]) => (
<label key={v}>
<input type="radio" name="contact" value={v}
checked={contact === v}
onChange={e => setContact(e.target.value)} /> {label}
</label>
));
<!-- Vue:同じ変数に v-model を結ぶ。picked には value の文字列が入る -->
<label><input type="radio" name="contact" value="email" v-model="picked"> メール</label>
<label><input type="radio" name="contact" value="phone" v-model="picked"> 電話</label>
- React で
checkedを渡すときはonChangeも渡します(渡さないと「読み取り専用」の警告が出て、クリックしても変わりません)。 - 送信をフレームワークに任せず
<form>で送るときは、name と value を省かないようにします。状態と結びつけても、サーバーに届くのは name=value です。
React のフォーム全般の値の取り方は、関連記事「Reactフォームinputの値取得|onChangeとuseRefの使い分け」で扱っています。
よくあるつまずきと直し方
この節では、ラジオボタンで起きやすい不具合を、原因と直し方の対応表で確かめられます。
| 症状 | 原因 | 直し方 |
|---|---|---|
| 2つ以上同時に選べてしまう | name が違う(綴り・大文字小文字・全角)、別の form に分かれている | 同じ form の中で name を完全に揃える |
| 文字をクリックしても選べない | label が無い、for と id が一致しない、id が重複している |
label で包むか、for と id を一致させる |
サーバーに on が届く |
value を書いていない | 各項目に value を書く |
| サーバーに何も届かない | 未選択・disabled・name が無い | required を付ける、disabled を外す、name を書く |
| Tab で止まらない・読み上げられない | input を display:none・visibility:hidden で隠した | 1×1 に縮めて clip で切る、または opacity:0 で重ねる |
| キーボードでフォーカスの位置が分からない | appearance:none で既定の輪が消えた | :focus-visible に outline を書く |
| 選択を外せない | 仕様(解除できない) | 「指定しない」の選択肢を足す |
| JS で checked=true にしたのに reset で戻る | 属性(defaultChecked)は変わっていない | 初期値を変えるなら setAttribute('checked','') か HTML を変える |
| React で「クリックしても変わらない」 | checked だけ渡して onChange が無い | onChange で state を更新する |
よくある質問
Q. ラジオボタンとは何ですか?
A. 複数の選択肢から1つだけを選ぶための丸い入力部品です。同じグループの別の項目を選ぶと、前の選択は自動で外れます。HTML では <input type="radio"> で作ります。
Q. ラジオボタンとチェックボックスの違いは? A. ラジオボタンは1つだけ選び、選択済みをもう一度クリックしても外れません。チェックボックスは0個から全部まで選べ、クリックで個別に外せます。「2つ以上あてはまることがあるか」で決めます。
Q. 名前の由来は? A. 以前のカーラジオの選局ボタンです。1つを押すと他のボタンが戻る仕組みが、「同時に1つしか選べない」性質と同じであることから名付けられました。
Q. クリックしても他の項目が外れません。
A. name が違っています。綴り・大文字小文字(h と H は別グループ)・半角全角を揃え、同じ form の中に置きます。
Q. 送信される値は何ですか?
A. グループごとに、選んだ1つの name=value です(例:contact=email)。value を書かないと on になり、未選択のグループと disabled の項目は送られません。
Q. 選択を解除する方法はありますか?
A. 利用者の操作では解除できません。JavaScript で checked=false にはできますが、任意の質問には「指定しない」「あてはまるものはない」の選択肢を足すのが基本です。
Q. 必須にするには?
A. グループのどれか1つに required を付けます。それだけでグループ全体が「どれか1つ必須」になり、未選択のまま送信するとブラウザが止めます。サーバー側でも確かめます。
Q. 色だけ変えたいです。
A. accent-color: #色; を input に付けます。手元の Chromium では選択時の点と枠が指定した色になり、Tab・読み上げはそのまま残りました。大きさは width・height で変えられます。
Q. 見た目を全部自作したいです。
A. appearance: none で既定の描画を消し、border・border-radius・::before で描きます。フォーカスの輪も消えるので :focus-visible に outline を書き、input を display:none にしないようにします。
Q. キーボードではどう選びますか? A. Tab でグループに入り(選択済みがあればそこに止まる)、矢印キーで移動すると同時に選択されます。Space で選択、Enter でフォームが送信されます。
Q. 横に並べるか縦に並べるか? A. 選択肢が3つ以上、または文字が長いときは縦に並べると、どの文字がどの丸のものか迷いません。「はい/いいえ」のような短い2択は横並びでも読めます。
Q. 選択肢が10個以上あります。 A. ラジオボタンでは縦に長くなるため、セレクト(プルダウン)か、検索つきの入力を検討します。比べて選ぶ必要がある項目なら、説明つきのラジオボタンのまま分類して並べます。
まとめ
- ラジオボタンは「1つだけ選ぶ」部品。同じ form の中で同じ name のものが1つのグループになり、名前は大文字小文字も区別される(手元で確認)。
- 送られるのは選んだ1つの
name=valueだけ。value が無いとon、未選択と disabled は届かない。サーバーでは許可した値と照合する。 - 既定の丸は 13px。label を結ぶと文字までクリックでき、包む形なら隙間も押せる。label の無いラジオボタンは作らない。
- Tab はグループに1回、矢印キーで移動と選択が同時に起きる。選択済みは自分では外せないので、任意の質問には「指定しない」を足す。
- 見た目は accent-color・appearance:none・画像の3通り。どれも Tab と読み上げが残ったが、input を display:none にすると両方消える。appearance:none では :focus-visible とコントラスト比 3:1 を自分で確かめる。
参考・出典
確認日はいずれも 2026年10月29日です。
- WHATWG「HTML Living Standard」4.10.5.1.16 Radio Button state (type=radio):https://html.spec.whatwg.org/multipage/input.html#radio-button-state-(type=radio)
- MDN「<input type="radio">」:https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/input/radio
- MDN「<label>」:https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/label
- MDN「accent-color」:https://developer.mozilla.org/ja/docs/Web/CSS/Reference/Properties/accent-color
- MDN「appearance」:https://developer.mozilla.org/ja/docs/Web/CSS/Reference/Properties/appearance
- MDN「RadioNodeList」:https://developer.mozilla.org/ja/docs/Web/API/RadioNodeList
- W3C「WAI-ARIA Authoring Practices Guide — Radio Group Pattern」:https://www.w3.org/WAI/ARIA/apg/patterns/radio/
- W3C「WCAG 2.2 — 1.4.11 Non-text Contrast」:https://www.w3.org/TR/WCAG22/#non-text-contrast
- W3C「WCAG 2.2 — 2.5.8 Target Size (Minimum)」:https://www.w3.org/TR/WCAG22/#target-size-minimum
- デジタル庁「デザインシステム ラジオボタン 使い方」:https://design.digital.go.jp/dads/components/radio/usage/
- React「<input>」:https://react.dev/reference/react-dom/components/input
- Vue.js「フォーム入力バインディング」:https://ja.vuejs.org/guide/essentials/forms
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ラジオボタンとは|チェックボックスとの違い・HTMLの作り方・CSSの変え方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。