コンポーネント(5): フォーム
form
div.form-group
label
属性
for="exampleInputEmail1"
Email address
input.form-control
属性
id="exampleInputEmail1"
type="email"
placeholder="Enter email"
aria-describedby="emailHelp"
small.form-text.text-muted
属性
id="emailHelp"
We'll never share your email with anyone else.
div.form-group
label
属性
for="exampleInputPassword1"
Password
input.form-control
属性
id="exampleInputPassword1"
type="password"
placeholder="Password"
div.form-check
button.btn.btn-primary.mt-2
属性
type="submit"
Submit
テキスト用コントロール( input
, select
, textarea
)には .form-control
を設定する(横幅100%で角丸ボーダー表示)。
input
+属性 type="(text|email|password|number|...)"
の場合ブラウザデフォルトの input
+属性 type="email"
input.form-control
+属性 type="email"
select
の場合ブラウザデフォルトの select
select.form-control
ブラウザデフォルトの select
+属性 multiple
select.form-control
+属性 multiple
textarea
の場合ブラウザデフォルトの textarea
textarea.form-control
input
+属性 type="file"
の場合ファイル選択コントロール( input
+属性 type="file"
)には.form-control-file
を設定する。
ブラウザデフォルトの input
+属性 type="file"
input.form-control-file
+属性 type="file"
(⇒ 注1)
.form-control
に .form-control-(sm|lg)
を追加する。
input
の場合input.form-control.form-control-sm
input.form-control
input.form-control.form-control-lg
select
の場合select.form-control.form-control-sm
select.form-control
select.form-control.form-control-lg
ブラウザデフォルトの input
+属性 type="range"
input.form-control-range
+attribute type="range"
(親要素幅にフィット)
readonly
属性
コントロールに属性 readonly
を設定すると値を変更できなくなる(選択はできるためコピーは可能)。
input.form-control
+属性 type="text" value="Read-only value" readonly
コントロールに .form-control-plaintext
を設定すると枠を除去し通常テキストと同じように表示する。
input.form-control-plaintext
+属性 type="text" value="Read-only value" readonly
form
form.form-inline
input.form-control-plaintext
div.form-check
の内部に配置 属性
div.form-check
(×3)
div.form-check
(×3)
div.form-check
に .form-check-inline
を追加
インライン配置のチェックボックス
インライン配置のラジオボタン
div.form-check.form-check-inline
(×3) 違いはここだけ
ラベルなしの場合は input
に .position-static
を追加
div.form-check
input.form-check-input.position-static
属性
id="blankCheckbox"
type="checkbox"
value="..."
aria-label="Checkbox without label"
div.form-check
(×3)
input.form-check-input.position-static
属性
id="blankRadio(1|2|3)"
type="radio"
value="..."
aria-label="Radio button without label"
checked
コントロール要素( input
, select
, textarea
, etc.)とそれに対応するラベル label
は div.form-group
の中に配置する。
form
に灰色, div.form-group
にオレンジのボーダー追加form
グリッド を利用してより高度でレスポンシブなフォームレイアウトを作成できる。次の例は単純に div.col
で左右2分割した場合(間が空く)。
form
div.row
div.col
(以下×2)
input.form-control
グリッドの行を div.form-row
に変更するとフォーム用の短めの間隔に設定する。
form
div.form-row
div.col
(以下 ×2)
input.form-control
公式ドキュメントより(構造表示のため .form-group
にオレンジのボーダーを追加)。
form
div.form-row
div.form-group.col-md-6
: md以上で(左側)6/12, 未満で上下配置
label
Email と input
Emaildiv.form-group.col-md-6
: md以上で(右側)6/12, 未満で上下配置
label
Password と input
Passworddiv.form-row
div.form-group.col-md-6
: md以上で(左側)6/12, 未満で上下配置
label
City と input
div.form-group.col-md-4
: md以上で(中央右)4/12, 未満で上下配置
label
State と select
Choose...div.form-group.col-md-2
: md以上で(右)2/12, 未満で上下配置
label
Zip と input
ラベルとコントロールを水平配置するレイアウト。
まとめdiv.form-group
に .row
を追加 ⇒ div.form-group.row
label
に .col-form-label
を追加 ⇒ label.col-form-label
.col-{breakpoint}-{width}
を用いるform
div.form-group.row
label.col-form-label
属性
.col-sm-2
for="inputEmail3"
Email
div.col-sm-10
input.form-control
: 属性は今までと同様(略)fieldset.form-group
div.row
legend.col-form-label
属性
.col-sm-2
.pt-0
Radios
div.col-sm-10
div.form-group.row
div.col-sm-2
Checkbox
div.col-sm-10
左が (label|legend).col-form-label
、右が フォームコントロール .form-control
の場合
(label|legend).col-form-control
に .col-form-label-(sm|lg)
を追加.form-control-(sm|lg)
を追加(⇒ サイズ設定 )左 label.col-form-label.col-form-label-sm
, 右 input.form-control.form-control-sm
左 label.col-form-label
, 右 input.form-control
左 label.col-form-label.col-form-label-lg
, 右 input.form-control.form-control-lg
グリッド を用いた列幅の設定例
構造form
div.form-row
div.col-7
(7/12), 内部はフォームコントロール (以下同様)div.col
(残り5/12を2等分 ⇒ 5/24)div.col
(残り5/12を2等分 ⇒ 5/24)列を .col
から .col(-sm|-md|-lg|-xl)?-auto
に変更すると幅をブラウザデフォルト値(内部コンテンツに対して可変)に設定する(⇒ グリッド - 幅の自動設定)。これを利用してフォーム要素を横(インライン)に並べて配置できる。
form
div.form-row.align-items-center
div.col-auto
属性
div.col-auto
属性
.my-1
label.sr-only
属性
for="inlineFormInputGroup"
Username
div.input-group
div.col-auto
属性
div.col-auto
属性
.my-1
button.btn.btn-primary
属性
type="submit"
Submit
次節のインラインフォーム - 基本例とほぼ同じだが幅smブレークポイント未満(<576px)の場合が異なる。インラインフォームは auto
を解除して横幅100%の縦配置に組み替えるが、こちらは常に auto
が有効で幅に応じて適宜要素を折り返す。
placeholder
属性を使いデフォルト値を表示してラベル代わりにする。その場合可視ユーザにラベルは不要になるが、スクリーンリーダ利用者のために label
を設定する。これは可視ユーザには不要なので.sr-only
(⇒ スクリーンリーダ)を設定して見えないようにする。レスポンシブ動作の設定例(公式ドキュメントの例を少し改良)。
構造form
div.form-row.align-items-center
div.col-sm-6.col-md-4.col-lg-3.my-1
+内部(隠れラベルとコントロール)div.col-sm-6.col-md-4.col-lg-3.my-1
+内部(インプットグループ)div.col-auto
+内部(チェックボックス)div.col-auto
+内部(ボタン)例1と構成は同じだが、幅変更に対して入力コントロールの幅が常に一定範囲を確保するようにレスポンシブ動作を個別調整している(インラインフォームはsmブレークポイントでの切り替えしかできないので、自分で細かく設定したい場合はこの方法を用いるとよい)。
div.col-sm-3(.my-1)
だが、実際に動作確認するとsmとmdの場合に幅不足でレイアウトが乱れる。そこで各ブレークポイント毎に細かく調整してできたもの。カスタムフォームコントロール を用いた例。
構造form
div.form-row.align-items-center
div.col-auto
属性
my-1
label
属性
.mr-sm-2
for="inlineFormCustomSelect"
Preference
div.col-auto
属性
my-1
select.custom-select
属性
.mr-sm-2
id="inlineFormCustomSelect"
style="width: auto;"
(⇒ 注3 )option ...
div.col-auto
属性
my-1
div.custom-control.custom-checkbox
属性
div.col-auto
属性
my-1
button.btn.btn-primary
属性
type="submit"
Submit
width: 100%;
になり横一列にならない。そこで本ページではカスタムスタイルを追加して横配置になるよう修正している。(form).form-inline
は構成要素を横に並べるレイアウト設定で、内部要素の設定を次のように変更する。
display: block;
から) display: flex;
に変更width: 100%;
から) width: auto;
に変更form.form-inline
label.sr-only
属性
for="inlineFormInputName2"
Name
input.form-control
属性
.my-1.mr-sm-2
id="inlineFormInputName2"
type="text"
placeholder="Jane Doe"
(ラベル代わりに用いる)label.sr-only
属性
for="inlineFormInputGroupUsername2"
Username
div.input-group
属性
.my-1.mr-sm-2
div.form-check
属性
button.btn.btn-primary
属性
.my-1
type="submit"
Submit
form.form-inline
label
属性
.my-1.mr-2
for="inlineFormCustomSelectPref"
Preference
select.custom-select
属性
.my-1.mr-sm-2
id="inlineFormCustomSelectPref"
option ...
div.custom-control.custom-checkbox
属性
button.btn.btn-primary
属性
.my-1
type="submit"
Submit
small.form-text(.text-muted)
を用い、アクセシビリティ用IDを付ける。
label
属性
for="inputPassword5"
Password
input.form-control
属性
id="inputPassword5"
type="password"
aria-describedby="passwordHelpBlock"
small.form-text.text-muted
属性
id="passwordHelpBlock"
Your password must be 8-20 characters long, ...
インラインレイアウトの場合は .form-text
を付けない。
form.form-inline
disabled
属性
コントロールに属性 disabled
を設定してdisabled状態にできる。またグループの親要素として fieldset
を使いそこに disabled
を設定するとグループ全体をdisabled状態にできる(⇒ 注4)。
form
fieldset
属性
disabled
(ここに設定)disabled
になるHTMLのバリデーション機能はバージョン5.0で導入された(詳しくはMDN - フォームデータの検証を参照)。今ではBootstrap 4の対応ブラウザ全てで使用できる(対応状況は Can I Use を参照)。しかし動作に環境依存がありどのブラウザでも同じ振る舞いにならない。またバリデーションメッセージはスクリーンリーダに対応していない(現状では認識困難)。
そこでBootstrap 4ではブラウザ依存を低減しスクリーンリーダがメッセージを判別できる独自方式を開発している。以下(公式ドキュメントと順番を入れ替えて)まずブラウザ標準の方法を示し、次にBootstrap方式を説明する。
required
を利用した簡単なバリデーションの例。レイアウトの説明は省略し、バリデーションに関するポイントのみ示す。ただし送信時の応答にブラウザ依存性があり、表示されるメッセージやその表現方法も異なることに注意(本例を用いて色々なブラウザで実行すれば確認できる)。
input
に属性 required
を追加pattern
属性を利用できる(正規表現で設定)
pattern="[0-9]{5}"
Bootstrap 4のバリデーション方式で作ったフォーム例。
HTMLはバリデーションに関するポイントのみ説明する。
HTMLまとめform
に次の2つを設定
novalidate
(ブラウザデフォルトのバリデーション動作を抑制).needs-validation
を用いる.form-control
required
属性)(div).valid-feedback
(div).invalid-feedback
次にBootstrap 4 (CSS)のバリデーション機能についてまとめる。
CSSまとめform
)に対し .was-validated
の有無で表示を制御
.form-control
を設定
.was-validated
+自分に :valid
が設定されると緑ボーダー表示.was-validated
+自分に :invalid
が設定されると赤ボーダー表示.valid-feedback
: 次の条件で表示される
.was-validated
が設定.form-control
に疑似クラス :valid
が設定.invalid-feedback
: 次の条件で表示される
.was-validated
が設定.form-control
に疑似クラス :invalid
が設定div.col*
や div.col-auto
などでもよい処理にはJavaScriptが必要。
JavaScriptまとめform
(今回は .needs-validation
)の submit
イベントハンドラを設定{form}.checkValidity()
:valid
疑似クラスが設定される:invalid
疑似クラスが設定されるevent.preventDefault()
event.stopPropagation()
.was-validated
を追加// DOM版(公式ドキュメントより)
(function() {
'use strict';
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
// jQuery版
$('.needs-validation').on('submit', function(event) {
if (!this.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
$(this).addClass('was-validated');
});
送信してサーバ側でバリデーションを行い、サーバ側から結果を反映したフォームを送り返す場合は疑似クラスは使えない。そこで代替手段として .is-valid
と .is-invalid
を用いて上記バリデーションと同じ表示効果を得ることができる。
form
に .was-validated
は不要.is-valid
.is-invalid
.valid-feedback
.invalid-feedback
次はその設定例。ブラウザから送信後にサーバでバリデーションを行い、First nameとLast nameは正しく後は不正という結果を送り返した状態を表したもの。
設定form
にはクラスや属性の追加なし.is-valid
を追加
.valid-feedback
は成功メッセージとして緑色表示.is-invalid
を追加
.invalid-feedback
は失敗メッセージとして赤色表示Bootstrapバリデーションはカスタムフォームコントロールに対応しており、通常のフォームコントロールと同じように使うことができる。次はその設定サンプルでデモ用に最初からバリデーション状態にしてある(送信もなし)。どれも入力すると表示が赤から緑に変化する。
設定.was-validated
を設定(説明用に最初からバリデーション状態にする)required
を追加
バリデーションの応答メッセージとして背景が半透明のツールチップをポップアップ表示できる。この方法を用いればレイアウト位置を変えずにバリデーション表示を行うことができる。
設定div.valid-feedback
⇒ div.valid-tooltip
に変更div.invalid-feedback
⇒ div.invalid-tooltip
に変更Bootstrap 4で導入された表示カスタマイズ、ブラウザ依存改善、アクセシビリティ向上のためのフォーム用部品。ブラウザデフォルトのコントロールを置き換えて利用できる。
div.custom-control.custom-checkbox
(×4)
3番目のチェックボックスは初期状態を - にしてある。これは :indeterminate
疑似クラスを用いたもので、次のコードで設定している(要JavaScript)。
document.getElementById('custom-check-3').indeterminate = true;
jQueryを利用する場合は次でもよい。
$('#custom-check-3').prop('indeterminate', true);
div.custom-control.custom-radio
(×4)
div.custom-control.custom-radio.custom-control-inline
(×4)
div.custom-control.custom-switch
(×2)
select.custom-select.custom-select-sm
select.custom-select
select.custom-select.custom-select-lg
属性 multiple
を設定した場合の表示
属性 size="3"
を設定した場合の表示
デフォルトの範囲は 0..100
、値は 50
、ステップは 1
に設定される。
label
属性
for="customRange1"
Example range
input.custom-range
属性
id="customRange1"
type="range"
範囲は min
と max
、値は value
で設定する。
label
属性
for="customRange2"
Example range
input.custom-range
属性
id="customRange2"
type="range"
min="0"
max="5"
value="1"
ステップは step
で設定する。
label
属性
for="customRange3"
Example range
input.custom-range
属性
id="customRange3"
type="range"
min="0"
step="0.5"
max="5"
value="3.5"
div.custom-file
カスタムファイルブラウザの表示 Browse は任意の文字に変更できる。
(4.2以降) label.custom-file-label
に data-browse="{表示する文字列}"
を追加することにより設定できる。以下は英語(en)、日本語(ja)、スペイン語(es)の設定例。
data-browse
の設定よりも優先度が高くなり、この設定は効かなくなる。より本格的にbootstrap.cssをソースコードからカスタマイズすることにより、label.custom-file-label
の言語属性(lang="{言語コード}"
)に対して表示を変更するように設定できる。ただしSass(.scss)とnode.js開発環境の知識が必要。詳しくは本節の公式ドキュメント本文参照。
Sassの知識がなくてもBootstrap CSSの後に自分用のカスタムCSSを追加すれば同じように設定できる。単純にすべて日本語に変更する場合はHTMLの head
ブロックの最後に次のCSS設定を追加すればよい。
<style>.custom-file-label::after { content: "ファイル選択"; }</style>
label
要素の lang
属性に応じて自動判別する場合は次のCSSコード例を参照。この場合はSass(Cscc)ソースレベルからのカスタマイズと全く同じ効果が得られる。
/* en(英語,デフォルト)はbootstrap.cssに設定済み(略) */
/* ja(日本語) */
.custom-file-input:lang(ja) ~ .custom-file-label::after {
content: "ファイル選択";
}
/* es(スペイン語) */
.custom-file-input:lang(es) ~ .custom-file-label::after {
content: "Elegir";
}
設定例は次の通り(en/ja/es)。
カスタムファイルブラウザは要素のデフォルト表示を( style="opacity: 0;"
で)消去しその上にカスタム表示を行っている。そのためファイル名表示のための別要素が必要で、その更新にJavaScriptコードを用いる。例を示す(jQuery版を本サイト全体に設定済)。
// DOM版
(function() {
window.addEventListener('load', function() {
var input = document.getElementById('custom-file');
input.addEventListener('change', function(event) {
var label = document.querySelector('[for="custom-file"]');
label.textContent = event.target.files[0].name;
}, false);
}, false);
})();
// jQuery版
$('#custom-file').on('change', function(event) {
$('[for="custom-file"]').text($(this).prop('files')[0].name);
});