ラジオボタン(選択連動・値取得パターン集)

フォーム 初級

このコンポーネントについて

ラジオボタンは複数の選択肢から1つだけを選ばせるUIコンポーネントです。 アンケートフォームや設定画面など、「どれか1つを選ばせる」場面で広く使われます。

単に選ばせるだけでなく、選択内容に応じて他のフォーム要素を制御したり、ボタン押下時に選んだ値を取得・表示したりするパターンは実務で特によく登場します。 このページでは2パターンを動くデモで確認でき、そのままコピペして使えます。

  • 選択連動による入力制御 — 特定の選択肢を選んだときだけテキストボックスを有効化し、それ以外は無効化・空欄にする
  • 値の取得と表示 — 決定ボタン押下時に選択中のラジオボタンの value 属性とラベルテキストを画面に表示する

実装のポイント・注意点

ラジオボタンで最も重要なのが name 属性の設定です。同じ name を持つボタンは自動的に1グループとして扱われ、1つ選ぶと他が解除されます。逆に name が異なると別グループになり、複数選択できてしまうので注意してください。

アクセシビリティの面では、関連するラジオボタンのまとまりを <fieldset> で囲み、<legend> でグループの説明を付けると、スクリーンリーダーが「このグループは何の質問か」を正しく読み上げます。見た目が気になる場合はCSSで fieldset の枠線を消すだけで対応できます。

ページ読み込み時に1つデフォルト選択(checked 属性)を付けておくと、「何も選ばないまま送信」というユーザーミスを防げます。また、選択状態のスタイルを変えたい場合は :checked 疑似クラスと +(隣接)セレクターを組み合わせるのが定番のCSS手法です。

デモ

Pattern 1 — 選択連動(テキストボックス制御)

あなたはAIを使って開発をしたことがありますか?

Pattern 2 — 値取得(決定ボタン)

ご利用のデバイスを教えてください

サンプルソース

3つのファイルを同じフォルダに保存し、index.html をブラウザで開くとすぐに動作確認できます。
ファイル名:index.html / style.css / script.js — 保存時の文字コードは UTF-8 を指定してください(Shift-JISだと日本語が文字化けします)。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>ラジオボタン サンプル</title>
  <link rel="stylesheet" href="./style.css">
</head>
<body>

<!-- Pattern 1: 選択連動(テキストボックス制御) -->
<div class="rb-pattern">
  <p class="rb-question">あなたはAIを使って開発をしたことがありますか?</p>
  <div class="rb-group">
    <label class="rb-label">
      <input type="radio" name="ai-experience" value="yes"> はい
    </label>
    <label class="rb-label">
      <input type="radio" name="ai-experience" value="no"> いいえ
    </label>
    <label class="rb-label">
      <input type="radio" name="ai-experience" value="unknown"> わからない
    </label>
  </div>
  <input type="text" id="ai-detail" class="rb-textbox"
         placeholder="開発で使ったAIを教えてください" disabled>
</div>

<!-- Pattern 2: 値取得(決定ボタン) -->
<div class="rb-pattern">
  <p class="rb-question">ご利用のデバイスを教えてください</p>
  <div class="rb-group">
    <label class="rb-label">
      <input type="radio" name="device" value="smartphone"> スマートフォン
    </label>
    <label class="rb-label">
      <input type="radio" name="device" value="pc"> PC・タブレット
    </label>
  </div>
  <button class="rb-submit-btn" id="device-submit">決定</button>
  <div class="rb-result" id="device-result" aria-live="polite"></div>
</div>

<script src="./script.js"></script>
</body>
</html>
/* === ラジオボタン パターン集 ===
   色を変えたいときは :root の変数を書き換えるだけでOKです */
:root {
  --color-accent:   #2B7FE8; /* フォーカス・選択時の強調色 */
  --color-danger:   #E53935; /* 警告テキスト色 */
  --color-text:     #1A2332; /* メインテキスト色 */
  --color-label:    #5A6A7A; /* ラベル文字色 */
  --color-border:   #D0D7E0; /* 通常時のボーダー色 */
  --color-bg:       #F4F6F9; /* カード背景色 */
  --color-disabled: #E8EDF4; /* disabled 時のテキストボックス背景色 */
  --color-hint:     #9AA5B4; /* ヒントテキスト色 */
}

/* 各パターンを囲むカード */
.rb-pattern {
  margin-bottom: 16px;
  padding: 20px;
  background: var(--color-bg);
  border-radius: 8px;
  max-width: 520px;
}
.rb-pattern:last-child { margin-bottom: 0; }

/* 質問テキスト */
.rb-question {
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
}

/* ラジオボタンの選択肢グループ */
.rb-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}

/* 各選択肢ラベル */
.rb-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--color-text);
  cursor: pointer;
}
.rb-label input[type="radio"] {
  width: 16px;
  height: 16px;
  accent-color: var(--color-accent);
  cursor: pointer;
  flex-shrink: 0;
}

/* テキストボックス(パターン1) */
.rb-textbox {
  width: 100%;
  padding: 9px 12px;
  border: 1.5px solid var(--color-border);
  border-radius: 6px;
  font-size: 14px;
  color: var(--color-text);
  background: #fff;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
  box-sizing: border-box;
  font-family: sans-serif;
}
.rb-textbox:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(43, 127, 232, 0.12);
}
/* disabled 状態: 背景をグレーにして視覚的に無効と分かるようにする */
.rb-textbox:disabled {
  background: var(--color-disabled);
  color: var(--color-hint);
  cursor: not-allowed;
}

/* 決定ボタン(パターン2) */
.rb-submit-btn {
  display: inline-block;
  padding: 9px 24px;
  background: var(--color-accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: sans-serif;
  transition: opacity 0.15s;
}
.rb-submit-btn:hover { opacity: 0.85; }

/* 結果表示エリア(パターン2) */
.rb-result {
  margin-top: 12px;
  min-height: 0;
  font-size: 14px;
  line-height: 1.6;
}
/* 値が入ったときにボーダーを表示 */
.rb-result.has-value {
  padding: 10px 14px;
  background: #fff;
  border: 1.5px solid var(--color-border);
  border-radius: 6px;
  color: var(--color-text);
}
/* 警告メッセージ */
.rb-result.has-error {
  color: var(--color-danger);
  font-weight: 600;
}

/* スマホ対応: 600px 以下でカードを全幅に */
@media (max-width: 600px) {
  .rb-pattern { max-width: 100%; }
}
// === Pattern 1: 選択連動(テキストボックス制御) ===
var aiDetailInput = document.getElementById('ai-detail');
var aiRadios = document.querySelectorAll('input[name="ai-experience"]');

aiRadios.forEach(function (radio) {
  radio.addEventListener('change', function () {
    if (this.value === 'yes') {
      // 「はい」選択時: テキストボックスを有効化
      aiDetailInput.disabled = false;
      aiDetailInput.focus();
    } else {
      // 「いいえ」「わからない」選択時: 内容をクリアして無効化
      aiDetailInput.value = '';
      aiDetailInput.disabled = true;
    }
  });
});


// === Pattern 2: 値取得(決定ボタン) ===
var deviceResult = document.getElementById('device-result');

document.getElementById('device-submit').addEventListener('click', function () {
  // 選択中のラジオボタンを取得する
  var checked = document.querySelector('input[name="device"]:checked');

  if (!checked) {
    // 未選択のときは警告を表示する
    deviceResult.textContent = '選択肢を選んでください';
    deviceResult.className = 'rb-result has-error';
    return;
  }

  // value と、最も近い label のテキストを取得する
  var value = checked.value;
  var label = checked.closest('label').textContent.trim();

  deviceResult.innerHTML =
    'value: ' + value + ' / ラベル: ' + label + '';
  deviceResult.className = 'rb-result has-value';
});


// === デモのリセット処理 ===
function resetDemo() {
  // パターン1: ラジオボタンを未選択に戻し、テキストボックスを空・無効化する
  aiRadios.forEach(function (radio) { radio.checked = false; });
  aiDetailInput.value = '';
  aiDetailInput.disabled = true;

  // パターン2: ラジオボタンを未選択に戻し、結果エリアをクリアする
  document.querySelectorAll('input[name="device"]').forEach(function (radio) {
    radio.checked = false;
  });
  deviceResult.textContent = '';
  deviceResult.className = 'rb-result';
}

AI用プロンプト

各パターンのプロンプトをコピーしてAIに渡すと、同様のコンポーネントを生成できます。

ChatGPTやClaudeにこのプロンプトを渡すと、同様のコンポーネントをゼロから生成・カスタマイズできます。ライブラリ指定や列数変更など、要件を追記して使うのがおすすめです。

※ このプロンプトを使ってもデモとまったく同じ動作にならない場合があります。AIの解釈や生成タイミングによって差が出ることをご了承ください。

💡 jQuery・Vue・React など特定のライブラリで実装したい場合は、プロンプトの末尾に「〇〇を使って実装してください」と追記してください。

Pattern 1 — 選択連動(テキストボックス制御)

# ラジオボタン(選択連動・テキストボックス制御)作成依頼

## 概要
ラジオボタンの選択内容に応じてテキストボックスの有効・無効を切り替えるフォームを実装してください。

## 要件
- 質問「あなたはAIを使って開発をしたことがありますか?」に対して「はい」「いいえ」「わからない」の3択ラジオボタンを表示する
- 「はい」を選択したとき、下部のテキストボックスを有効化し入力できるようにする
- 「いいえ」または「わからない」を選択したとき、テキストボックスの入力内容を空にして disabled 状態にする
- リセットボタンで全選択・入力内容を初期状態に戻す

## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要

## 動作詳細
input[type=radio] の change イベントで選択値を判定する。
テキストボックスの disabled 属性を動的に付け外しし、無効時は背景色をグレーにして視覚的にも分かるようにすること。

## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。

Pattern 2 — 値取得(決定ボタン)

# ラジオボタン(値取得・決定ボタン)作成依頼

## 概要
ラジオボタンで1つ選んで「決定」ボタンを押すと、選択した選択肢の value 値とラベルテキストを画面に表示するUIを実装してください。

## 要件
- 「ご利用のデバイスを教えてください」という質問に対して「スマートフォン」(value: smartphone)・「PC・タブレット」(value: pc)の2択ラジオボタンを表示する
- 「決定」ボタンを押すと、選択中の value とラベルテキストを結果エリアに表示する(例:value: smartphone / ラベル: スマートフォン)
- 未選択のまま「決定」を押した場合は「選択肢を選んでください」と警告を表示する
- リセットボタンでラジオボタンの選択と結果エリアの表示をリセットする

## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要

## 動作詳細
document.querySelector('input[name="device"]:checked') で選択中の要素を取得する。
null のときは警告、取得できたときは value と closest('label').textContent.trim() を結果エリアに表示する。

## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。