チェックボックス(選択連動・複数値取得パターン集)

フォーム 初級

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

チェックボックスは複数の選択肢から自由にいくつでも選ばせるUIコンポーネントです。 同意確認・フィルター・アンケートなど、「複数選択を許可したい」場面で広く使われます。

このページでは、チェック状態に応じて入力欄を連動制御するパターンと、多数の選択肢をグリッドレイアウトで並べて複数選択後に値を一括取得するパターンの2種類を動くデモで確認でき、そのままコピペして使えます。

  • 選択連動による入力制御 — 特定の選択肢にチェックを入れたときだけテキストボックスを有効化し、外したときは無効化・空欄にする
  • グリッド配置の複数選択 — 多数の選択肢をフレックスボックスで横並び・折り返しし、チェックボックスとテキストが縦横に揃ったグリッド状に配置する
  • 複数値の一括取得と表示 — 決定ボタン押下時にチェック中の全選択肢の value とラベルテキストを一覧表示する

実装のポイント・注意点

チェックボックスとラジオボタンの使い分けは明確で、「1つしか選べない」ならラジオボタン、「複数・0個でも可」ならチェックボックスです。同意確認(利用規約への同意)のように「単独のON/OFF」を表す場面でもチェックボックスが使われます。

<label> タグで <input> を内包するか、forid を紐付けることで、ラベルのテキスト部分をクリックしてもチェックのON/OFFができます。スマートフォンでは小さなチェックボックス本体をタップするのが難しいため、このラベル操作の対応はUX上とても重要です。

チェック中の要素をまとめて取得するには querySelectorAll('input[type="checkbox"]:checked') が便利です。全選択・全解除ボタンを実装したい場合も、全チェックボックスに対して .checked = true/false を一括設定するだけで対応できます。複数ページにまたがるフォームでは localStorage を使って選択状態を一時保存する手法も実務でよく使われます。

デモ

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

利用したいサービスをすべて選んでください

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="cb-pattern">
  <p class="cb-question">利用したいサービスをすべて選んでください</p>
  <div class="cb-group">
    <label class="cb-label">
      <input type="checkbox" name="service" value="newsletter" id="cb-newsletter">
      メールマガジンを受け取る
    </label>
    <label class="cb-label">
      <input type="checkbox" name="service" value="feature-news">
      新機能のお知らせを受け取る
    </label>
    <label class="cb-label">
      <input type="checkbox" name="service" value="campaign">
      キャンペーン情報を受け取る
    </label>
  </div>
  <input type="text" id="email-input" class="cb-textbox"
         placeholder="受信するメールアドレスを入力してください" disabled>
</div>

<!-- Pattern 2: グリッド複数選択 + 値一括取得 -->
<div class="cb-pattern">
  <p class="cb-question">好きな料理をすべて選んでください(複数選択可)</p>
  <div class="cb-grid" id="food-group">
    <!-- script.js で動的生成 -->
  </div>
  <button class="cb-submit-btn" id="food-submit">決定</button>
  <div class="cb-result" id="food-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; /* ヒントテキスト色 */
}

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

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

/* パターン1: チェックボックスの縦並びグループ */
.cb-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}

/* パターン2: チェックボックスのグリッド(横並び・折り返し) */
.cb-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 0;
  margin-bottom: 14px;
}

/* グリッドの各アイテム: 3列固定でチェックボックスを縦横に揃える */
.cb-grid-item {
  width: calc(100% / 3);
}

/* 各選択肢ラベル(縦並び・グリッド共通) */
.cb-label,
.cb-grid-item label {
  display: flex;
  gap: 8px;
  font-size: 13px;
  color: var(--color-text);
  cursor: pointer;
}

/* パターン1(縦並び): 1行テキストなので中央揃えでOK */
.cb-label { align-items: center; }

/* パターン2(グリッド): テキスト折り返し時もチェックボックス位置が揃うよう上揃えにする */
.cb-grid-item label { align-items: flex-start; }

.cb-label input[type="checkbox"],
.cb-grid-item input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--color-accent);
  cursor: pointer;
  flex-shrink: 0;
  /* テキスト1行目の高さに視覚的に合わせる */
  margin-top: 1px;
}

/* テキストボックス(パターン1) */
.cb-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;
}
.cb-textbox:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(43, 127, 232, 0.12);
}
/* disabled 状態: 背景をグレーにして視覚的に無効と分かるようにする */
.cb-textbox:disabled {
  background: var(--color-disabled);
  color: var(--color-hint);
  cursor: not-allowed;
}

/* 決定ボタン(パターン2) */
.cb-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;
}
.cb-submit-btn:hover { opacity: 0.85; }

/* 結果表示エリア(パターン2) */
.cb-result {
  margin-top: 12px;
  font-size: 14px;
  line-height: 1.6;
}
.cb-result.has-value {
  padding: 10px 14px;
  background: #fff;
  border: 1.5px solid var(--color-border);
  border-radius: 6px;
  color: var(--color-text);
}
.cb-result.has-value ul {
  margin: 0;
  padding: 0 0 0 18px;
}
.cb-result.has-value li {
  margin-bottom: 4px;
}
.cb-result.has-value li:last-child { margin-bottom: 0; }
.cb-result.has-error {
  color: var(--color-danger);
  font-weight: 600;
}

/* スマホ対応: 480px 以下でグリッドアイテムを2列に */
@media (max-width: 480px) {
  .cb-pattern { max-width: 100%; }
  .cb-grid-item { width: 50%; }
}
/* 320px 以下では1列に */
@media (max-width: 320px) {
  .cb-grid-item { width: 100%; }
}
// === 料理の選択肢データ ===
var FOODS = [
  { value: 'sushi',         label: '寿司' },
  { value: 'ramen',         label: 'ラーメン' },
  { value: 'tempura',       label: '天ぷら' },
  { value: 'yakiniku',      label: '焼肉' },
  { value: 'soba',          label: 'そば' },
  { value: 'gyoza',         label: '餃子' },
  { value: 'karaage',       label: 'から揚げ' },
  { value: 'hamburg',       label: 'ハンバーグ' },
  { value: 'omurice',       label: 'オムライス' },
  { value: 'curry',         label: 'カレーライス' },
  { value: 'okonomiyaki',   label: 'お好み焼き' },
  { value: 'chahan',        label: 'チャーハン' },
  { value: 'nikujaga',      label: '肉じゃが' },
  { value: 'oyakodon',      label: '親子丼' },
  { value: 'caesar-salad',  label: 'シーザーサラダ' },
  { value: 'pasta-tomato',  label: 'トマトとバジルのパスタ' },
  { value: 'cream-stew',    label: 'チキンのクリームシチュー' },
  { value: 'avocado-salad', label: 'アボカドとエビのサラダ' },
  { value: 'steak',         label: 'ビーフステーキ' },
  { value: 'ahijo',         label: 'エビとマッシュルームのアヒージョ' },
];

// パターン2のチェックボックスをDOMに生成する
var foodGroup = document.getElementById('food-group');
FOODS.forEach(function (food) {
  var item = document.createElement('div');
  item.className = 'cb-grid-item';

  var label = document.createElement('label');
  var input = document.createElement('input');
  input.type = 'checkbox';
  input.name = 'food';
  input.value = food.value;

  label.appendChild(input);
  label.appendChild(document.createTextNode(' ' + food.label));
  item.appendChild(label);
  foodGroup.appendChild(item);
});


// === Pattern 1: 選択連動(テキストボックス制御) ===
var newsletterCb = document.getElementById('cb-newsletter');
var emailInput   = document.getElementById('email-input');

newsletterCb.addEventListener('change', function () {
  if (this.checked) {
    // 1つ目にチェックが入ったらテキストボックスを有効化する
    emailInput.disabled = false;
    emailInput.focus();
  } else {
    // チェックを外したら入力内容をクリアして無効化する
    emailInput.value   = '';
    emailInput.disabled = true;
  }
});


// === Pattern 2: 値一括取得(決定ボタン) ===
var foodResult = document.getElementById('food-result');

document.getElementById('food-submit').addEventListener('click', function () {
  // チェック中のすべての要素を取得する
  var checked = document.querySelectorAll('input[name="food"]:checked');

  if (checked.length === 0) {
    // 未選択のときは警告を表示する
    foodResult.textContent = '1つ以上選んでください';
    foodResult.className   = 'cb-result has-error';
    return;
  }

  // 選択中の value とラベルテキストを一覧表示する
  var items = Array.from(checked).map(function (cb) {
    var label = cb.closest('label').textContent.trim();
    return 'value: ' + cb.value + ' / ラベル: ' + label;
  });

  foodResult.innerHTML =
    '
    ' + items.map(function (t) { return '
  • ' + t + '
  • '; }).join('') + '
'; foodResult.className = 'cb-result has-value'; }); // === デモのリセット処理 === function resetDemo() { // パターン1: チェックを外し、テキストボックスを空・無効化する document.querySelectorAll('input[name="service"]').forEach(function (cb) { cb.checked = false; }); emailInput.value = ''; emailInput.disabled = true; // パターン2: 全チェックを外し、結果エリアをクリアする document.querySelectorAll('input[name="food"]').forEach(function (cb) { cb.checked = false; }); foodResult.textContent = ''; foodResult.className = 'cb-result'; }

AI用プロンプト

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

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

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

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

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

# チェックボックス(選択連動・テキストボックス制御)作成依頼

## 概要
チェックボックスのチェック状態に応じてテキストボックスの有効・無効を切り替えるフォームを実装してください。

## 要件
- 「利用したいサービスをすべて選んでください」という設問に対して3つのチェックボックスを表示する
  - 「メールマガジンを受け取る」(value: newsletter)
  - 「新機能のお知らせを受け取る」(value: feature-news)
  - 「キャンペーン情報を受け取る」(value: campaign)
- 1つ目「メールマガジンを受け取る」にチェックを入れたとき、下部のテキストボックスを有効化して入力できるようにする
- 1つ目のチェックを外したとき、テキストボックスの入力内容を空にして disabled 状態にする
- 2つ目・3つ目のチェック状態はテキストボックスの有効・無効に影響しない
- リセットボタンで全チェック・入力内容を初期状態に戻す

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

## 動作詳細
1つ目のチェックボックスの change イベントで checked 状態を判定する。
テキストボックスの disabled 属性を動的に付け外しし、無効時は背景色をグレーにすること。

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

Pattern 2 — グリッド複数選択 + 値一括取得

# チェックボックス(グリッド複数選択・値一括取得)作成依頼

## 概要
多数の選択肢をグリッドレイアウトで並べ、複数チェック後に決定ボタンで選択値を一括取得・表示するUIを実装してください。

## 要件
- 「好きな料理をすべて選んでください(複数選択可)」という設問に対して20個のチェックボックスを表示する
- チェックボックスは横並び・折り返しで表示し、各アイテムは幅 calc(100% / 3) にして3列のグリッド状に配置する
- 「決定」ボタンを押すと、チェック中の全選択肢の value とラベルテキストを結果エリアにリスト表示する
- 未チェックのまま「決定」を押した場合は「1つ以上選んでください」と警告を表示する
- リセットボタンで全チェックと結果エリアをリセットする

## 選択肢データ(20個)
寿司(sushi)、ラーメン(ramen)、天ぷら(tempura)、焼肉(yakiniku)、そば(soba)、
餃子(gyoza)、から揚げ(karaage)、ハンバーグ(hamburg)、オムライス(omurice)、
カレーライス(curry)、お好み焼き(okonomiyaki)、チャーハン(chahan)、
肉じゃが(nikujaga)、親子丼(oyakodon)、シーザーサラダ(caesar-salad)、
トマトとバジルのパスタ(pasta-tomato)、チキンのクリームシチュー(cream-stew)、
アボカドとエビのサラダ(avocado-salad)、ビーフステーキ(steak)、
エビとマッシュルームのアヒージョ(ahijo)

## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要(スマホでは2列になるよう調整)

## 動作詳細
選択肢はJSで配列データから動的生成する。
querySelectorAll('input[name="food"]:checked') でチェック中要素を取得する。
closest('label').textContent.trim() でラベルテキストを取得する。

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