mcpField
B
bootstrap-forms

bootstrap-forms

github.com/sjnimsデザイン・UI41 回インストール
リポジトリ

bootstrap-forms について

Bootstrap 5.3でフォームを作るフロントエンド開発者向けのリファレンススキルです。コントロール、レイアウト、バリデーション、アクセシビリティを扱います。

主な機能

  1. 01フォームコントロールとサイズ設定
  2. 02セレクト、データリスト、スイッチ
  3. 03入力グループとフローティングラベル
  4. 04縦、横、グリッドのレイアウト
  5. 05バリデーション状態とアクセシビリティ属性

活用シーン

  1. 01ログイン・登録フォームの作成
  2. 02設定ページや管理パネルの設計
  3. 03フォームのバリデーション表示
  4. 04スクリーンリーダー対応の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sjnims/bootstrap-expert --skill bootstrap-forms

インストール後、Claude Code で/bootstrap-formsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

examples/
accessibility-patterns.html
floating-labels-form.html
horizontal-form.html
inline-search-form.html
toggle-buttons.html
validation-form.html
references/
accessibility-checklist.md
form-reference.md
validation-approaches.md

詳細

Bootstrap 5.3 フォーム

Bootstrap は、コントロール、レイアウト、検証状態、入力グループなど、包括的なフォームのスタイルを提供します。

フォームコントロール

テキスト入力
<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control" id="email" placeholder="[email protected]">
</div>

<div class="mb-3">
  <label for="password" class="form-label">Password</label>
  <input type="password" class="form-control" id="password">
</div>
サイズ

周囲の要素と入力欄のサイズを合わせたり、重要なフィールドを強調したりするには、サイズクラスを使用します。ヒーローセクションや主要な CTA には .form-control-lg を使用します。ツールバーやインラインフォームなど、コンパクトな UI には .form-control-sm を使用します。

<input class="form-control form-control-lg" type="text" placeholder="Large input">
<input class="form-control" type="text" placeholder="Default input">
<input class="form-control form-control-sm" type="text" placeholder="Small input">
無効化と読み取り専用

ユーザーがまったく操作できないフィールドには disabled を使用します。値を表示して選択できるようにしつつ、編集はできないようにする場合は readonly を使用します。フォームのスタイルを適用せずに値を表示するには、readonly とともに .form-control-plaintext を使用します。

<input class="form-control" type="text" disabled value="Disabled input">
<input class="form-control" type="text" readonly value="Readonly input">
<input class="form-control-plaintext" type="text" readonly value="Readonly plain text">
ファイル入力
<div class="mb-3">
  <label for="file" class="form-label">Upload file</label>
  <input class="form-control" type="file" id="file">
</div>


<input class="form-control" type="file" multiple>
カラーピッカー
<div class="mb-3">
  <label for="color" class="form-label">Color picker</label>
  <input type="color" class="form-control form-control-color" id="color" value="#0d6efd">
</div>
テキストエリア
<div class="mb-3">
  <label for="textarea" class="form-label">Comments</label>
  <textarea class="form-control" id="textarea" rows="3"></textarea>
</div>
ヘルプテキスト

補足説明には .form-text を使用します。aria-describedby でヘルプテキストを入力欄に関連付けると、入力欄にフォーカスしたときにスクリーンリーダーが読み上げます。

<div class="mb-3">
  <label for="password" class="form-label">Password</label>
  <input type="password" class="form-control" id="password" aria-describedby="passwordHelp">
  <div id="passwordHelp" class="form-text">Must be 8+ characters with one uppercase letter.</div>
</div>

入力欄にヘルプテキストと検証フィードバックの両方がある場合は、aria-describedby で両方を指定します。

<div class="mb-3">
  <label for="email" class="form-label">Email</label>
  <input type="email" class="form-control is-invalid" id="email"
         aria-describedby="emailHelp emailError" aria-invalid="true">
  <div id="emailHelp" class="form-text">We'll never share your email.</div>
  <div id="emailError" class="invalid-feedback">Please enter a valid email address.</div>
</div>

セレクト

<select class="form-select">
  <option selected>Choose an option</option>
  <option value="1">Option One</option>
  <option value="2">Option Two</option>
  <option value="3">Option Three</option>
</select>


<select class="form-select" multiple>
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>


<select class="form-select form-select-lg">...</select>
<select class="form-select form-select-sm">...</select>


<select class="form-select" size="3">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
  <option value="4">Four</option>
</select>

size 属性を指定すると、multiple による選択を有効にしなくても複数のオプションを表示できます。見た目の大きさを変える .form-select-lg とは異なり、size は一度に表示するオプションの数を制御します。すべての選択肢を表示すると使いやすくなる、小規模なオプションリストに使用します。

データリスト

データリストは、テキスト入力用のオートコンプリート候補を提供します。自由入力の柔軟性と、定義済みオプションの利便性を兼ね備えています。

<label for="browser" class="form-label">Choose a browser</label>
<input class="form-control" list="browsers" id="browser" placeholder="Type to search...">
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Safari">
  <option value="Edge">
  <option value="Opera">
</datalist>

list 属性にデータリストの id を指定して、入力欄とデータリストを関連付けます。ユーザーは自由に入力することも、候補から選択することもできます。データリストのスタイルはブラウザー標準で、ブラウザーごとに異なります。Bootstrap の .form-control で入力欄のスタイルは設定できますが、ドロップダウンの見た目はカスタマイズできません。

チェックボックスとラジオボタン

チェックボックス
<div class="form-check">
  <input class="form-check-input" type="checkbox" id="check1">
  <label class="form-check-label" for="check1">Default checkbox</label>
</div>
<div class="form-check">
  <input class="form-check-input" type="checkbox" id="check2" checked>
  <label class="form-check-label" for="check2">Checked checkbox</label>
</div>
不確定状態のチェックボックス

チェックボックスが「一部選択済み」の状態を表す場合は、不確定状態を使用します。一部の子項目だけが選択されている「すべて選択」パターンに便利です。この状態は JavaScript で設定する必要があり、HTML 属性では設定できません。

<div class="form-check">
  <input class="form-check-input" type="checkbox" id="checkIndeterminate">
  <label class="form-check-label" for="checkIndeterminate">Select all items</label>
</div>

<script>
  document.getElementById('checkIndeterminate').indeterminate = true;
</script>
ラジオボタン
<div class="form-check">
  <input class="form-check-input" type="radio" name="radios" id="radio1" checked>
  <label class="form-check-label" for="radio1">First radio</label>
</div>
<div class="form-check">
  <input class="form-check-input" type="radio" name="radios" id="radio2">
  <label class="form-check-label" for="radio2">Second radio</label>
</div>
スイッチ

通知の有効化やダークモードの切り替えなど、即座に反映されるオン/オフ設定には、チェックボックスよりスイッチを使用してください。複数選択のオプションや、変更の適用に送信操作が必要な場合には、チェックボックスを使用します。

<div class="form-check form-switch">
  <input class="form-check-input" type="checkbox" role="switch" id="switch1">
  <label class="form-check-label" for="switch1">Default switch</label>
</div>
<div class="form-check form-switch">
  <input class="form-check-input" type="checkbox" role="switch" id="switch2" checked>
  <label class="form-check-label" for="switch2">Checked switch</label>
</div>

iOS 17.4 以降の Safari でネイティブの触覚フィードバックを有効にするには、switch 属性を追加します。

<div class="form-check form-switch">
  <input class="form-check-input" type="checkbox" role="switch" id="nativeSwitch" switch>
  <label class="form-check-label" for="nativeSwitch">Native haptics (iOS 17.4+)</label>
</div>
インライン
<div class="form-check form-check-inline">
  <input class="form-check-input" type="checkbox" id="inline1">
  <label class="form-check-label" for="inline1">1</label>
</div>
<div class="form-check form-check-inline">
  <input class="form-check-input" type="checkbox" id="inline2">
  <label class="form-check-label" for="inline2">2</label>
</div>
逆レイアウト

.form-check-reverse を使用すると、入力欄を反対側に配置できます。ラベルが先、チェックボックスまたはラジオボタンが後になります。設定インターフェースや RTL レイアウトに適した、入力欄を右揃えにするスタイルです。

<div class="form-check form-check-reverse">
  <input class="form-check-input" type="checkbox" id="reverseCheck">
  <label class="form-check-label" for="reverseCheck">Reverse checkbox</label>
</div>

<div class="form-check form-check-reverse">
  <input class="form-check-input" type="radio" name="reverseRadios" id="reverseRadio1">
  <label class="form-check-label" for="reverseRadio1">First reverse radio</label>
</div>

トグルボタン

ボタンスタイルのチェックボックスやラジオボタンを作成するには、.btn-check を使用します。標準的なフォームチェックとは異なり、トグルボタンではラベルに .btn クラスを適用してボタンの見た目にしながら、チェックボックス/ラジオボタンのセマンティクスを維持します。セグメントコントロール、フィルターの切り替え、オプションの選択に使用します。

チェックボックスの切り替え
<input type="checkbox" class="btn-check" id="btn-check" autocomplete="off">
<label class="btn btn-primary" for="btn-check">Single toggle</label>

<input type="checkbox" class="btn-check" id="btn-check-2" checked autocomplete="off">
<label class="btn btn-primary" for="btn-check-2">Checked</label>

<input type="checkbox" class="btn-check" id="btn-check-3" disabled autocomplete="off">
<label class="btn btn-primary" for="btn-check-3">Disabled</label>
ラジオボタンの切り替え

単一選択動作にするには、name 属性でラジオボタンのトグルをグループ化します。

<input type="radio" class="btn-check" name="options" id="option1" autocomplete="off" checked>
<label class="btn btn-secondary" for="option1">Checked</label>

<input type="radio" class="btn-check" name="options" id="option2" autocomplete="off">
<label class="btn btn-secondary" for="option2">Radio</label>

<input type="radio" class="btn-check" name="options" id="option3" autocomplete="off">
<label class="btn btn-secondary" for="option3">Radio</label>
アウトラインスタイル

より軽やかな枠線付きの見た目にするには、.btn-outline-* を使用します。

<input type="checkbox" class="btn-check" id="btn-outlined" autocomplete="off">
<label class="btn btn-outline-primary" for="btn-outlined">Toggle</label>

<input type="radio" class="btn-check" name="opts" id="success" autocomplete="off" checked>
<label class="btn btn-outline-success" for="success">Success</label>

<input type="radio" class="btn-check" name="opts" id="danger" autocomplete="off">
<label class="btn btn-outline-danger" for="danger">Danger</label>
アクセシビリティ

トグルボタンは基本的にチェックボックスまたはラジオボタンであるため、スクリーンリーダーでは「オン/オフ」として読み上げられます。「ボタン/ボタン押下」と読み上げられるボタンプラグインのトグルとは異なります。セマンティクスに応じて選択してください。オン/オフや選択状態を表すコントロールには、トグルボタンを使用します。

レンジ

レンジ入力はスライダーコントロールを提供します。ブラウザー間で一貫したスタイルにするには、.form-range を使用します。

<label for="range" class="form-label">Range slider</label>
<input type="range" class="form-range" id="range">


<input type="range" class="form-range" min="0" max="100" step="5">
現在の値を表示する

JavaScript と <output> 要素を使って、現在の範囲値をリアルタイムで表示します。

<label for="volumeRange" class="form-label">
  Volume: <output id="volumeValue">50</output>
</label>
<input type="range" class="form-range" id="volumeRange"
       min="0" max="100" value="50"
       oninput="document.getElementById('volumeValue').textContent = this.value">

スライダーを動かすと oninput イベントが発生し、すぐにフィードバックが表示されます。関連性が明確になるよう、<output> 要素をラベル内またはその近くに配置します。より複雑なケースでは、インラインハンドラーの代わりに個別のイベントリスナーを使用します。

入力グループ

入力グループを使って、フォームコントロールに関連する要素を視覚的に結び付けます。よくあるパターンとして、通貨記号、測定単位、入力欄の横に配置するアクションボタンなどがあります。

基本
<div class="input-group mb-3">
  <span class="input-group-text">@</span>
  <input type="text" class="form-control" placeholder="Username">
</div>

<div class="input-group mb-3">
  <input type="text" class="form-control" placeholder="Email">
  <span class="input-group-text">@example.com</span>
</div>

<div class="input-group mb-3">
  <span class="input-group-text">$</span>
  <input type="text" class="form-control" placeholder="Amount">
  <span class="input-group-text">.00</span>
</div>
ボタン付き
<div class="input-group mb-3">
  <input type="text" class="form-control" placeholder="Search...">
  <button class="btn btn-outline-secondary" type="button">Search</button>
</div>

<div class="input-group mb-3">
  <button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
    Dropdown
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">Action</a></li>
  </ul>
  <input type="text" class="form-control">
</div>
サイズ
<div class="input-group input-group-sm">...</div>
<div class="input-group">...</div>
<div class="input-group input-group-lg">...</div>
折り返しの動作

入力グループは、デフォルトで flex-wrap: wrap によって折り返されます。コンテンツの幅にかかわらず、すべての要素を1行に収めるには .flex-nowrap を追加します。

<div class="input-group flex-nowrap">
  <span class="input-group-text">@</span>
  <input type="text" class="form-control" placeholder="Username">
</div>
角丸の制限

先頭または末尾の位置に非表示要素(.d-none または display: none を使用)があると、隣接する要素の角丸スタイルが崩れます。これは既知の Bootstrap の制限です。回避するには、非表示要素を入力グループの外に移動するか、要素を DOM 内に残す必要がある場合は可視性ユーティリティを使用します。

分割ドロップダウンボタン

入力グループ内の分割ボタンドロップダウンには .dropdown-toggle-split を使用します。これにより、メインのアクションボタンの横に独立したドロップダウントリガーが作成されます。

<div class="input-group">
  <button type="button" class="btn btn-outline-secondary">Action</button>
  <button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split"
          data-bs-toggle="dropdown" aria-expanded="false">
    <span class="visually-hidden">Toggle Dropdown</span>
  </button>
  <ul class="dropdown-menu dropdown-menu-end">
    <li><a class="dropdown-item" href="#">Option 1</a></li>
    <li><a class="dropdown-item" href="#">Option 2</a></li>
  </ul>
  <input type="text" class="form-control" placeholder="Enter value">
</div>

フローティングラベル

フローティングラベルを使うと、フォーカス時にラベルが入力欄内へ移動する、すっきりとしたコンパクトなフォームデザインにできます。ログインやサインアップのようなシンプルなフォームに最適です。入力欄の横にヘルプテキストや複雑な検証メッセージが必要な場合は使用を避けてください。

<div class="form-floating mb-3">
  <input type="email" class="form-control" id="floatingEmail" placeholder="[email protected]">
  <label for="floatingEmail">Email address</label>
</div>

<div class="form-floating mb-3">
  <input type="password" class="form-control" id="floatingPassword" placeholder="Password">
  <label for="floatingPassword">Password</label>
</div>

<div class="form-floating">
  <textarea class="form-control" placeholder="Leave a comment" id="floatingTextarea"></textarea>
  <label for="floatingTextarea">Comments</label>
</div>
フローティングラベルと検証を含む入力グループ

フローティングラベルを入力グループや検証と組み合わせる場合は、特別な構造が必要です。.form-floating を .input-group の内側に配置し、入力グループに .has-validation を追加して、検証フィードバックを .form-floating の外側かつ .input-group の内側に配置します。

<div class="input-group has-validation">
  <span class="input-group-text">@</span>
  <div class="form-floating is-invalid">
    <input type="text" class="form-control is-invalid" id="floatingUsername"
           placeholder="Username" required>
    <label for="floatingUsername">Username</label>
  </div>
  <div class="invalid-feedback">Please choose a username.</div>
</div>

.has-validation クラスを指定すると、検証フィードバックがある場合に適切な角丸スタイルが適用されます。このクラスがないと、検証状態によって入力グループの外観が崩れることがあります。

フォームのレイアウト

フォームの複雑さと利用可能なスペースに応じて、レイアウトを選択します。

縦型(デフォルト)

ほとんどのフォームでは縦型レイアウトを使用します。最もシンプルで、モバイルでも使いやすい形式です。ラベルが入力欄の上に並ぶため、内容を簡単に確認できます。

<form>
  <div class="mb-3">
    <label for="email" class="form-label">Email</label>
    <input type="email" class="form-control" id="email">
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
横型

十分な幅があり、よりコンパクトな外観にしたい場合は横型を使用します。短いフィールドが多い設定ページや管理パネルに最適です。

<form>
  <div class="row mb-3">
    <label for="email" class="col-sm-2 col-form-label">Email</label>
    <div class="col-sm-10">
      <input type="email" class="form-control" id="email">
    </div>
  </div>
  <div class="row">
    <div class="col-sm-10 offset-sm-2">
      <button type="submit" class="btn btn-primary">Submit</button>
    </div>
  </div>
</form>
インライン
<form class="row row-cols-lg-auto g-3 align-items-center">
  <div class="col-12">
    <input type="text" class="form-control" placeholder="Username">
  </div>
  <div class="col-12">
    <select class="form-select">
      <option selected>Choose...</option>
    </select>
  </div>
  <div class="col-12">
    <button type="submit" class="btn btn-primary">Submit</button>
  </div>
</form>
グリッドレイアウト
<form>
  <div class="row g-3">
    <div class="col-md-6">
      <label for="firstName" class="form-label">First name</label>
      <input type="text" class="form-control" id="firstName">
    </div>
    <div class="col-md-6">
      <label for="lastName" class="form-label">Last name</label>
      <input type="text" class="form-control" id="lastName">
    </div>
    <div class="col-12">
      <label for="address" class="form-label">Address</label>
      <input type="text" class="form-control" id="address">
    </div>
    <div class="col-md-6">
      <label for="city" class="form-label">City</label>
      <input type="text" class="form-control" id="city">
    </div>
    <div class="col-md-4">
      <label for="state" class="form-label">State</label>
      <select id="state" class="form-select">
        <option selected>Choose...</option>
      </select>
    </div>
    <div class="col-md-2">
      <label for="zip" class="form-label">Zip</label>
      <input type="text" class="form-control" id="zip">
    </div>
    <div class="col-12">
      <button type="submit" class="btn btn-primary">Submit</button>
    </div>
  </div>
</form>

アクセシビリティの基本

フォームでスクリーンリーダーをサポートし、WCAG に準拠するには、適切なアクセシビリティ属性が必要です。

ラベル

for 属性と id 属性を使って、ラベルを常に入力欄に関連付けます。

<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email">

視覚的に非表示にするラベルには .visually-hidden を使用します。

<label for="search" class="visually-hidden">Search</label>
<input type="search" class="form-control" id="search" placeholder="Search...">
ヘルプテキスト

aria-describedby を使って、ヘルプテキストを入力欄に関連付けます。

<input type="password" class="form-control" id="password" aria-describedby="passwordHelp">
<div id="passwordHelp" class="form-text">Must be 8+ characters.</div>
検証状態

支援技術が無効なフィールドを認識できるようにします。

<input type="email" class="form-control is-invalid" aria-invalid="true" aria-describedby="emailError">
<div id="emailError" class="invalid-feedback">Please enter a valid email.</div>
必須フィールド
<input type="text" class="form-control" required aria-required="true">

検証

ブラウザーのデフォルト
<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-6">
    <label for="validationCustom01" class="form-label">First name</label>
    <input type="text" class="form-control" id="validationCustom01" required>
    <div class="valid-feedback">Looks good!</div>
    <div class="invalid-feedback">Please provide a first name.</div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit form</button>
  </div>
</form>

<script>
// JavaScript for validation
(function () {
  'use strict'
  var forms = document.querySelectorAll('.needs-validation')
  Array.prototype.slice.call(forms).forEach(function (form) {
    form.addEventListener('submit', function (event) {
      if (!form.checkValidity()) {
        event.preventDefault()
        event.stopPropagation()
      }
      form.classList.add('was-validated')
    }, false)
  })
})()
</script>
検証状態

<input type="text" class="form-control is-valid">
<div class="valid-feedback">Looks good!</div>


<input type="text" class="form-control is-invalid">
<div class="invalid-feedback">Please provide a valid value.</div>
検証ツールチップ

位置を指定するツールチップ形式の検証を行いたい場合は、フィードバックメッセージの代わりに .valid-tooltip と .invalid-tooltip を使用します。ツールチップは絶対配置の浮動メッセージとして表示されるため、親要素に position: relative を設定する必要があります。

<div class="col-md-4 position-relative">
  <label for="city" class="form-label">City</label>
  <input type="text" class="form-control is-invalid" id="city" required>
  <div class="valid-tooltip">Looks good!</div>
  <div class="invalid-tooltip">Please provide a valid city.</div>
</div>

フィードバックメッセージがフォームレイアウトを乱す場合や、より目立つ視覚的な表示が必要な場合は、ツールチップが役立ちます。フォーム内では一貫して使用し、ツールチップとフィードバックメッセージを混在させないでください。

よくある間違い

間違い問題修正方法
プレースホルダーをラベルとして使用するアクセシビリティに対応できず、入力すると表示されなくなります常に<label>要素を使用します
カスタム検証でnovalidateを指定しないブラウザーのデフォルトのフィードバックとカスタムフィードバックの両方が表示されます<form>にnovalidateを追加します
入力グループに.has-validationを付け忘れる検証時に角丸が崩れます.input-groupに.has-validationを追加します
for属性のないラベルスクリーンリーダーがラベルと入力欄を関連付けられませんforを入力欄のidと一致させます
ヘルプテキストにaria-describedbyを指定しないヘルプテキストが読み上げられませんaria-describedbyで関連付けます
aria-invalid="true"を省略するスクリーンリーダーがエラー状態を認識できません.is-invalidとともにaria-invalidを追加します
入力グループの最初または最後の項目にdisplay: noneを使用する隣接する要素の角丸が崩れます.visually-hiddenを使用するか、グループの外に移動します

検証方法の比較についてはreferences/validation-approaches.mdを、アクセシビリティ要件の全容についてはreferences/accessibility-checklist.mdを参照してください。

追加リソース

参照ファイル
  • references/form-reference.md - フォームクラスの完全なリファレンス
  • references/validation-approaches.md - ブラウザー、カスタム、サーバーサイドの検証方法の比較
  • references/accessibility-checklist.md - 必須属性とテスト手順
サンプルファイル
  • examples/validation-form.html - フォーム検証のパターン
  • examples/floating-labels-form.html - フローティングラベルを使用した登録フォームとログインフォーム
  • examples/horizontal-form.html - 水平レイアウト、サイズ設定、ラジオボタン、読み取り専用表示
  • examples/inline-search-form.html - ナビゲーションバーの検索、フィルター、ツールバー、ニュースレターのフォーム
  • examples/toggle-buttons.html - チェックボックスとラジオボタンのトグルボタン、アウトラインスタイル
  • examples/accessibility-patterns.html - ARIA属性を使用したアクセシブルなフォーム

コメント