Bootstrap: フォームとフォームバリデーション
最終更新:2026-08-26
1. はじめに
(1) 前提条件
- レッスン12: テーブル
(2) 🎯 学習内容
form-control、form-select、form-check-inputを使用したコントロールのスタイル設定- グリッドとインラインレイアウトを使用したフォームのレイアウト
input-groupを使用したプレフィックス/サフィックス要素の追加needs-validationを使用したクライアントサイドバリデーションの実装form-floatingを使用したフローティングラベルの実装
(3) 課題
ボブはユーザー登録ページを開発しており、名前、メール、パスワード、国選択、利用規約への同意を収集する必要があります。Bootstrapのフォームクラスを使用すれば、CSSスタイルを一切書かずに、HTML構造とバリデーションロジックだけに集中できます。
(4) 解決策
フォームはユーザーと対話するための主要な方法です。Bootstrapは、統一されたフォームコントロールスタイルとバリデーションフィードバックシステムを提供し、フォーム開発を効率的で美しくします。
理解のポイント: Bootstrapフォーム = ネイティブブラウザコントロールのビューティーフィルターです。
<input>、<select>、<textarea>のすべての要素が.form-controlでラップされると、統一されたスタイル、間隔、インタラクティブフィードバックが付与されます。
(5) メリット
Bootstrapのフォームユーティリティクラスを使用することで、CSSスタイルコードを一切書かずに、HTML構造とバリデーションロジックに集中できます。
2. フォームコントロール
すべてのテキストベースの入力コントロールは .form-control を使用します。
▶ サンプル 基本的なフォーム
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4">
<form>
<div class="mb-3">
<label for="name" class="form-label">Full Name</label>
<input type="text" class="form-control" id="name" placeholder="Enter your name">
</div>
<div class="mb-3">
<label for="country" class="form-label">Country</label>
<select class="form-select" id="country">
<option selected>Choose...</option>
<option value="us">United States</option>
<option value="jp">Japan</option>
<option value="uk">United Kingdom</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Skills</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="html" checked>
<label class="form-check-label" for="html">HTML</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="css">
<label class="form-check-label" for="css">CSS</label>
</div>
</div>
<div class="mb-3">
<label class="form-label">Experience Level</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="level" id="beginner" checked>
<label class="form-check-label" for="beginner">Beginner</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="level" id="advanced">
<label class="form-check-label" for="advanced">Advanced</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</body>
</html>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
3. フォームコントロールの種類
| コントロール | クラス | 説明 |
|---|---|---|
| テキスト入力 | form-control |
1行テキスト、メール、パスワード、URLなど |
| テキストエリア | form-control |
複数行テキスト(rowsが行数を制御) |
| セレクト | form-select |
ドロップダウン選択ボックス |
| チェックボックス | form-check-input |
複数選択 |
| ラジオボタン | form-check-input |
単一選択(同じ名前で相互排他) |
| 範囲 | form-range |
スライダー |
| ファイル | form-control |
ファイルアップロード |
4. フォームレイアウト
(1) グリッドレイアウト
<div class="row">
<div class="col-md-6 mb-3">
<label for="firstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="firstName">
</div>
<div class="col-md-6 mb-3">
<label for="lastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="lastName">
</div>
</div>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
(2) インラインフォーム
<form class="row g-3">
<div class="col-auto">
<input type="search" class="form-control" placeholder="Search...">
</div>
<div class="col-auto">
<button class="btn btn-primary" type="submit">Go</button>
</div>
</form>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
(3) 水平フォーム
<div class="row mb-3">
<label for="email2" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email2">
</div>
</div>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
5. 入力グループ
<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="Amount">
<span class="input-group-text">.00</span>
</div>
<div class="input-group mb-3">
<button class="btn btn-outline-secondary" type="button">Search</button>
<input type="text" class="form-control" placeholder="Type to search">
</div>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
6. フォームバリデーション
<form class="row g-3 needs-validation" novalidate>
<div class="col-md-4">
<label for="validationName" class="form-label">First Name</label>
<input type="text" class="form-control" id="validationName" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please enter your name.</div>
</div>
<div class="col-md-4">
<label for="validationEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="validationEmail" required>
<div class="valid-feedback">Valid email!</div>
<div class="invalid-feedback">Please provide a valid email.</div>
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</form>
<script>
(function() {
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>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
(1) バリデーションフィードバックスタイル
| クラス | 条件 | 表示方法 |
|---|---|---|
.valid-feedback |
入力が有効 | 緑色テキスト |
.invalid-feedback |
入力が無効 | 赤色テキスト |
.was-validated |
フォーム送信後 | すべてのフィードバックをトリガー |
is-valid / is-invalid |
手動制御 | ステータスボーダー |
7. その他のフォーム例
▶ サンプル 完全な登録フォーム(バリデーション付き)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Signup Form</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4">
<div class="card mx-auto" style="max-width: 500px;">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">Create Account</h4>
</div>
<div class="card-body">
<form class="needs-validation" novalidate>
<div class="mb-3">
<label for="fullName" class="form-label">Full Name</label>
<input type="text" class="form-control" id="fullName" required>
<div class="invalid-feedback">Please enter your name.</div>
</div>
<div class="mb-3">
<label for="signupEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="signupEmail" required>
<div class="invalid-feedback">Please enter a valid email.</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" minlength="8" required>
<div class="invalid-feedback">Password must be at least 8 characters.</div>
</div>
<div class="col-md-6">
<label for="confirmPwd" class="form-label">Confirm</label>
<input type="password" class="form-control" id="confirmPwd" required>
<div class="invalid-feedback">Passwords must match.</div>
</div>
</div>
<div class="mb-3">
<label for="countrySelect" class="form-label">Country</label>
<select class="form-select" id="countrySelect" required>
<option value="">Choose...</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="jp">Japan</option>
</select>
<div class="invalid-feedback">Please select a country.</div>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="agreeTerms" required>
<label class="form-check-label" for="agreeTerms">I agree to the terms and conditions</label>
<div class="invalid-feedback">You must agree to continue.</div>
</div>
<button type="submit" class="btn btn-primary w-100">Register</button>
</form>
</div>
</div>
</div>
<script>
(function() {
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>
</body>
</html>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
▶ サンプル 検索フォーム(入力グループ)
<form class="container py-4">
<div class="row g-2">
<div class="col-md-3">
<select class="form-select">
<option selected>All Categories</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
<option value="books">Books</option>
</select>
</div>
<div class="col-md-6">
<div class="input-group">
<input type="search" class="form-control" placeholder="Search products...">
<button class="btn btn-primary" type="submit">Search</button>
</div>
</div>
<div class="col-md-3">
<button class="btn btn-outline-secondary w-100" type="button">Advanced Filters</button>
</div>
</div>
</form>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
▶ サンプル インラインフォーム
<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">
<input type="password" class="form-control" placeholder="Password">
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="rememberMe">
<label class="form-check-label" for="rememberMe">Remember me</label>
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Sign In</button>
</div>
</form>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
▶ サンプル フローティングラベルフォーム
<div class="container py-4" style="max-width: 400px;">
<form>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingEmail" placeholder="name@example.com">
<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 mb-3">
<select class="form-select" id="floatingSelect">
<option value="">Choose...</option>
<option value="free">Free Plan</option>
<option value="pro">Pro Plan</option>
<option value="enterprise">Enterprise</option>
</select>
<label for="floatingSelect">Subscription Plan</label>
</div>
<div class="form-floating mb-3">
<textarea class="form-control" id="floatingTextarea" style="height: 100px" placeholder="Comments"></textarea>
<label for="floatingTextarea">Message</label>
</div>
<button class="btn btn-primary w-100">Submit</button>
</form>
</div>
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
(1) フォームレイアウト決定フロー
flowchart TD
A[フォームの設計を開始] --> B{フィールド数}
B -->|1-3| C[単純なスタック<br/>mb-3で区切る]
B -->|4-8| D{グループ化が必要?}
D -->|はい| E[グリッドレイアウト<br/>row + col-*]
D -->|いいえ| F[インライン/水平レイアウト]
B -->|8以上| G[複数カラムのグリッド<br/>または段階的表示]
E --> H{プレフィックスが必要?}
H -->|はい| I[input-group]
H -->|いいえ| J[直接 form-control]
F --> K{フローティングラベル?}
K -->|はい| L[form-floating]
K -->|いいえ| M[通常のラベル]
出力: Bootstrap 5.3でスタイルされたコンポーネント(例:ボタン、カード、カルーセル、折りたたみなど)の効果。ページはデフォルトのBootstrapテーマ(ライト)とレスポンシブグリッドを使用しています。
| フォームコントロール | クラス | 適用可能なデータ型 |
|---|---|---|
| 1行テキスト | form-control |
名前、メール、パスワード |
| 複数行テキスト | form-control (textarea) |
コメント、説明 |
| ドロップダウン選択 | form-select |
国、カテゴリ、オプション |
| チェックボックス | form-check-input |
複数選択、利用規約同意 |
| ラジオボタン | form-check-checkbox-input (radio) |
性別、レベル、オプション |
| スライダー | form-range |
価格帯、評価 |
| ファイルアップロード | form-control (file) |
画像、ドキュメント |
| 入力グループのバリアント | コードパターン | 用途 |
|---|---|---|
| プレフィックステキスト | input-group-text + form-control |
金額 $、ユーザー名 @ プレフィックス |
| サフィックステキスト | form-control + input-group-text |
サフィックス .00、単位 px |
| プレフィックスボタン | button + form-control |
検索ボックス |
| サフィックスボタン | form-control + button |
パスワード表示切替 |
| 複数要素 | 複数の input-group-text |
日付範囲、組み合わせ入力 |
| バリデーション状態 | クラス | ボーダー | フィードバックテキスト |
|---|---|---|---|
| 有効 | is-valid |
緑 | valid-feedback |
| 無効 | is-invalid |
赤 | invalid-feedback |
| 送信後 | was-validated |
自動切替 | すべてのフィードバックをトリガー |
| ツールチップ | valid-tooltip と組み合わせ |
上記と同じ | バブルスタイルのヒント |
❓ よくある質問
.form-control はデフォルトで width: 100% です。幅を制御するには、グリッドカラム (col-*) の内側に配置するか、style="width: 300px" を追加します。.form-label の目的は何ですか?<label> の間隔 (margin-bottom: 0.5rem) とフォントサイズを統一します。なくても動作しますが、一貫性のために追加することをお勧めします。<div class="invalid-feedback"> の中身は任意のテキストにできます。さらに、setCustomValidity() メソッドもサポートされています。input-group には複数の input-group-text、form-control、ボタンを含めることができます。:placeholder-shown 疑似クラスを使用しており、モダンブラウザでサポートされています。IEはサポートしていませんが、IEはメンテナンスが終了しています。非常に古いブラウザをサポートする必要がある場合は、従来のラベルレイアウトを使用することをお勧めします。📖 まとめ
- テキストコントロールには
form-control、ドロップダウンにはform-select、チェックボックス/ラジオボタンにはform-check-inputを使用 - フォームグループの区切りには
mb-3を使用、複数カラムのレイアウトにはグリッドのrow+col-*を使用 - 入力フィールドの前後にテキストやボタンを追加するには
input-groupを使用 - フォームバリデーション:
needs-validation+ JS +was-validated+valid-feedback/invalid-feedback
📝 練習問題
- ⭐ 完全な登録フォームを作成してください: 名前(テキスト)、年齢(数値)、国(セレクト)、パスワード(パスワード)、パスワード確認。すべてBootstrapスタイルを使用すること。
- ⭐⭐ 課題1のフォームにバリデーションを実装してください: 名前は必須で2〜20文字、パスワードは8文字以上、メールは正しい形式であること。条件を満たさない場合、赤い
invalid-feedbackを表示すること。 - ⭐⭐⭐ 検索入力グループを作成してください: 左側にカテゴリ選択用の
form-select+ 中央にform-control検索ボックス + 右側に検索ボタン。
前のレッスン: テーブル · 次のレッスン: カルーセルとモーダル