Components (5): Forms
form
div.form-group
label Attribute
for="exampleInputEmail1"Email addressinput.form-control Attributes
id="exampleInputEmail1"type="email"placeholder="Enter email"aria-describedby="emailHelp"small.form-text.text-muted Attribute
id="emailHelp"We'll never share your email with anyone else.div.form-group
label Attribute
for="exampleInputPassword1"Passwordinput.form-control Attributes
id="exampleInputPassword1"type="password"placeholder="Password"div.form-check
input.form-check-input Attributes
id="exampleCheck1"type="checkbox"label.form-check-label Attribute
for="exampleCheck1"Check me outbutton.btn.btn-primary.mt-2 Attribute
type="submit"SubmitSet .form-control to input controls ( input, select, textarea ) ⇒
displays with a rounded border by 100% width
input +attribute type="(text|email|password|number|...)"Browser default input +attribute type="email"
input.form-control +attribute type="email"
selectBrowser default select
select.form-control
Browser default select +attribute multiple
select.form-control +attribute multiple
textareaBrowser default textarea
textarea.form-control
input +attribute type="file"Set .form-control-file to file input controls (input +attribute type="file" )
Browser default input +attribute type="file"
input.form-control-file +attribute type="file" (⇒ Note 1)
Add .form-control-(sm|lg) to .form-control
inputinput.form-control.form-control-sm
input.form-control
input.form-control.form-control-lg
selectselect.form-control.form-control-sm
select.form-control
select.form-control.form-control-lg
Browser default input +attribute type="range"
input.form-control-range +attribute type="range" (fits to the parent width)
Set readonly attribute to prevent the modification of the input value (it is still available for copy and paste).
input.form-control +attribute type="text" value="Read-only value" readonlyWith setting .form-control-plaintext to a form control, it hides borders and shows like a plain text but margins/paddings are preserved.
input.form-control-plaintext +attribute type="text" value="Read-only value" readonlyform
input.form-control-plaintext Attributes
type="text"readonlyvalue="email@example.com"form.form-inline ⇒ see Inline form - Example
input.form-control-plaintext
div.form-check : Stacked (top to bottom) as default Attribute
.form-check-inline to arrange inline (left to right)input.form-check-input Attributes
type="checkbox" or "radio"id="{control-id}"checked.position-static with no labellabel.form-check-label Attribute
for="{control-id}"div.form-check (×3)
input.form-check-input Attributes
id="defaultCheck(1|2|3)"type="checkbox"value="..."checked (first item only)disabled (last item only)label.form-check-label Attribute
for="defaultCheck(1|2|3)"Default checkbox (1|2) or Disabled checkbox (grayed automatically)div.form-check (×3)
input.form-check-input Attributes
id="exampleRadios(1|2|3)"type="radio"name="exampleRadios"value="..."checked (first item only)disabled (last item only)label.form-check-label Attribute
for="exampleRadios(1|2|3)"Default radio (1|2) or Disabled radio (grayed automatically)Add .form-check-inline to div.form-check
Inline checkboxes
Inline radios
div.form-check.form-check-inline
Add .position-static to input
div.form-check
input.form-check-input.position-static Attributes
id="blankCheckbox"type="checkbox"value="..."aria-label="Checkbox without label"div.form-check (×3)
input.form-check-input.position-static Attributes
id="blankRadio(1|2|3)"type="radio"value="..."aria-label="Radio button without label"checkedA control element ( input , select , textarea , etc.) and its associated label label are set inside div.form-group
form , orange border to div.form-group to indicate structureform
More complex and responsive forms can be built using Grid . The first example below divides a row div.row with two columns div.col. But it sets slightly wider paddings (gutters) on center.
form
div.row
div.col (×2)
input.form-controlChanging from.row to .form-row adjusts paddings (tighter and compact) for form layouts.
form
div.form-row
div.col (×2)
From the official document (orange border to .form-group to indicate structure)
form
div.form-row
div.form-group.col-md-6 : 6/12 (left) on ≥md, stacked on <md
label Email and input Emaildiv.form-group.col-md-6 : 6/12 (right) on ≥md, stacked on ≤md
label Password and input Passworddiv.form-row
div.form-group.col-md-6 : 6/12 (left) on ≥md, stack on <md
label City and inputdiv.form-group.col-md-4 : 4/12 (center) on ≥md, stacked on <md
label State and select Choose...div.form-group.col-md-2 : 2/12 (right) on ≥md, stacked on <md
label Zip and input.row to div.form-group ⇒ div.form-group.row.col-form-label to label ⇒ label.col-form-label.col-{breakpoint}-{width} for responsive layoutform
div.form-group.row
label.col-form-label Attributes
.col-sm-2for="inputEmail3"Emaildiv.col-sm-10
input.form-control (same attributes as former examples)fieldset.form-group
div.row
legend.col-form-label Attributes
.col-sm-2.pt-0Radiosdiv.col-sm-10
div.form-group.row
div.col-sm-2
Checkboxdiv.col-sm-10
On horizontal forms, a form control and its corresponding label should have the same sizing.
.col-form-label-(sm|lg) to (label|legend).col-form-control.form-control-(sm|lg) (see Sizing)Left: label.col-form-label.col-form-label-sm, Right: input.form-control.form-control-sm
Left: label.col-form-label, Right: input.form-control
Left: label.col-form-label.col-form-label-lg, Right: input.form-control.form-control-lg
Example using Grid to set column widths.
Structureform
div.form-row
div.col-7 - Form control (City) insidediv.col - Form control (State) insidediv.col - Form control (Zip) insideChanging the columns' class from .col to .col(-sm|-md|-lg|-xl)?-auto sets widths to browser defaults (⇒ Grid - Variable width content). It can be used for inline layouts.
form
div.form-row.align-items-center
div.col-auto Attribute
.my-1label.sr-only (⇒ Note 2) Attribute
for="inlineFormInput"Nameinput.form-control Attributes
id="inlineFormInput"type="text"placeholder="Jane Doe" (behaves as an actual label for visible users)div.col-auto Attribute
.my-1label.sr-only Attribute
for="inlineFormInputGroup"Usernamediv.input-group
div.col-auto Attribute
.my-1div.form-check
input.form-check-input Attributes
id="autoSizingCheck"type="checkbox"label.form-check-label Attribute
for="autoSizingCheck"Remember mediv.col-auto Attribute
.my-1button.btn.btn-primary Attribute
type="submit"SubmitThis example is nearly the same as the next Inline form - Basic example. The defference is a behavior below sm breakpoint (<576px). An inline form cancels auto and switchs to the vertically stacked layout. The example above always fold elements to the next row with auto.
placeholder attribute is often used for the role of label with displaying a default value (no label is needed for visible users in this case). But label should be needed for screenreader users. Utilize .sr-only (⇒ Screenreaders) for visible uses.An example for responsive behaviors (modified from the official document example).
Structureform
div.form-row.align-items-center
div.col-sm-6.col-md-4.col-lg-3.my-1 +Inside (hidden label + form control)div.col-sm-6.col-md-4.col-lg-3.my-1 +Inside (input group)div.col-auto +Inside (checkbox)div.col-auto +Inside (button)It looks same as example 1 on width≥lg (992px). But responsive widths are adjusted for that the form control and the input group has enough widths on sm and md breakpoints.
div.col-sm-3(.my-1). But widths (of a form control and a input group) are insufficient on sm and md. Above example adjusts responsive behaviors on all widths.Inline variation with custom form controls (modified from the official document example).
Structureform
div.form-row.align-items-center
div.col-auto Attribute
.my-1label Attributes
.mr-sm-2for="inlineFormCustomSelect"Preferencediv.col-auto Attribute
.my-1select.custom-select Attributes
.mr-sm-2id="inlineFormCustomSelect"style="width: auto;" (⇒ Note 3 )option ...div.col-auto Attribute
.my-1div.custom-control.custom-checkbox Attribute
.mr-sm-2input.custom-control-input Attributes
id="customControlAutosizing"type="checkbox"label.custom-control-label Attribute
for="customControlAutosizing"Remember my preferencediv.col-auto Attribute
.my-1button.btn.btn-primary Attribute
type="submit"Submitselect (width: 100%; by default). As the result, a custom select does not arrange inline. This example uses a custom style to fix this problem.(form).form-inline can be used for inline (horizontal) layouts. It sets layout settings as follows.
display:block to display:flexwidth:100% to width:autoauto. Use Spacing utilities to adjust them.label for accessibility. Add .sr-only if it is not needed for visible uses (⇒ Note 2).form.form-inline
label.sr-only Attribute
for="inlineFormInputName2"Nameinput.form-control Attributes
.my-1.mr-sm-2id="inlineFormInputName2"type="text"placeholder="Jane Doe" (actual label for visible users)label.sr-only Attribute
for="inlineFormInputGroupUsername2"Usernamediv.input-group Attribute
.my-1.mr-sm-2div.form-check Attribute
.my-1.mr-sm-2input.form-check-input Attributes
id="inlineFormCheck"type="checkbox"label.form-check-label Attribute
for="inlineFormCheck"Remember mebutton.btn.btn-primary Attributes
.my-1type="submit"Submit.form-check-inline to a checkbox (or a radio) block div.form-check. Outer form.form-inline sets everything for inline checkboxes and radios.form.form-inline
label Attributes
.my-1.mr-2for="inlineFormCustomSelectPref"Preferenceselect.custom-select Attribute
.my-1.mr-sm-2id="inlineFormCustomSelectPref"option ...div.custom-control.custom-checkbox Attributes
.my-1.mr-sm-2input.custom-control-input Attributes
id="customControlInline"type="checkbox"label.custom-control-label Attribute
for="customControlInline"Remember my preferencebutton.btn.btn-primary Attributes
.my-1type="submit"SubmitUse small.form-text(.text-muted) for stacked or horizontal layouts. Considering accessibility, a help text should have ID to be referenced by aria-describedby attribute.
label Attribute
for="inputPassword5"Passwordinput.form-control Attributes
id="inputPassword5"type="password"aria-describedby="passwordHelpBlock"small.form-text.text-muted Attribute
id="passwordHelpBlock"Your password must be 8-20 characters long, ...Remove .form-text for inline layouts.
form.form-inline
label Attribute
for="inputPassword3"Passwordinput.form-control Attributes
.mx-sm-3id="inputPassword6"type="password"aria-describedby="passwordHelpInline"small.text-muted Attribute
id="passwordHelpInline"Must be 8-20 characters long.You can set the attribute disabled to disable a control element. You can also wrap control elements with a fieldset and set disabled to disable all controls inside (⇒ Note 4).
form
fieldset Attribute
disableddisabledHTML validation was introduced in HTML version 5.0 (see MDN - Form data validation). Now it is supported for all modern browsers (see Can I Use). But browsers' default behaviors are inconsistent and also their validation messages are difficult to recognize for assistive technologies (e.g. screen readers).
Bootstrap has made thier custom validation styles since version 4.0. It is made for improvement of consistency among browsers and message accessibility for assistive technologies.
The example below shows browser default validation behaviors. Note that each behavior heavily varies among browsers (check this example for yourself with various browsers).
Summaryrequired to all inputs to validate (enables browser's validation)pattern
pattern="[0-9]{5}"The example below demonstrates Bootstrap 4 style validation.
HTML markups.
HTML summaryform as below
novalidate (disables browser default validation).needs-validation used in this page.form-controlrequired(div).valid-feedback(div).invalid-feedbackUses Bootstrap 4 CSS validation.
CSS summary.was-validated to an ancestor (typically a form)
.form-control to control elements to validate
.was-validated to an ancestor and :valid to itself.was-validated to an ancestor and :invalid to itself.valid-feedback : displays on
.was-validated to an ancestor:valid to a former .form-control.invalid-feedback : displays on
.was-validated to an ancestor:invalid to a former .form-controlNeeds JavaScript.
JavaScript summarysubmit event handler to the corresponding form (e.g. .needs-validation ){form}.checkValidity()
:valid pseudo-class to valid controls:invalid pseudo-class to invalid controlsevent.preventDefault()event.stopPropagation().was-validated to the form// DOM version (from official document)
(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 version
$('.needs-validation').on('submit', function(event) {
if (!this.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
$(this).addClass('was-validated');
});
Bootstrap also supports for server-side validation behaviors. But pseudo-class :valid or :invalid cannot be set from server-side. Bootstrap CSS provides .is-valid and .is-invalid for alternatives of corresponding pseudo-classes.
form (.was-validated is not needed)
.is-valid.is-invalid.valid-feedback.invalid-feedbackThe example below is showing First name and Last name are valid but all others are invalid.
Summaryform (no class or attribute added).is-valid to first two form controls (First name, Last name)
.is-invalid to all other controls
Bootstrap 4 validation supports custom form controls. The example below demonstrates validation behaviors of supported custom form controls.
Settings.was-validated to form (demonstrates validating behaviors)required to controls as below
Changing from .(valid|invalid)-feedback to .(valid|invalid)-tooltip displays a validation feedback message as a tooltip popup with translucent background.
div.valid-feedback ⇒ div.valid-tooltipdiv.invalid-feedback ⇒ div.invalid-tooltipBootstrap 4 custom form controls can be used for further display customization and cross browser consistency.
div.custom-control.custom-checkbox (×4)
input.custom-control-input Attributes
id="custom-check-(1|2|3|4)"type="checkbox"checkeddisabledlabel.custom-control-label Attribute
for="custom-check-(1|2|3|4)"Custom checkbox (1|2|3|4) (disabled)?Initial state of the third checkbox is set to - . It is an example of :indeterminate pseudo-class and set by the following code (JavaScript required).
document.getElementById('custom-check-3').indeterminate = true;
Or using jQuery:
$('#custom-check-3').prop('indeterminate', true);
div.custom-control.custom-radio (×4)
input.custom-control-input Attributes
id="custom-radio-(1|2|3|4)"type="radio"name="custom-radios"checkeddisabledlabel.custom-control-label Attribute
for="custom-radio-(1|2|3|4)"Custom radio (1|2|3|4) (disabled)?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
On setting attribute multiple
On setting attribute size="3"
As default, range is set to 0..100 , value is set to 50 , step is set to 1.
label Attribute
for="customRange1"Example rangeinput.custom-range Attributes
id="customRange1"type="range"Set range with min and max, value with value.
label Attribute
for="customRange2"Example rangeinput.custom-range Attributes
id="customRange2"type="range"min="0"max="5"value="1"Set step with step.
label Attribute
for="customRange3"Example rangeinput.custom-range Attributes
id="customRange3"type="range"min="0"step="0.5"max="5"value="3.5"div.custom-file
input.custom-file-input Attributes
id="custom-file"type="file"lang="en"label.custom-file-label Attribute
for="custom-file"Choose fileYou can change the file browser's default text (Browse on the right) to the arbitrary string.
(≥ 4.2) Adding data-browse="{String}" to label.custom-file-label changes the string: English(en), Japanese(ja), and Spanish(es) examples below.
data-browse attribute.You can control strings with the language attribute lang="{language code}" (of label.custom-file-label) by customizing Bootstrap Scss source code (Sass language and node.js development knowledge required). See official document for detail.
You can also control strings with the language attribute by adding some custom CSS (requires only CSS knowledge). If you just want to change to another string, you can append a short CSS as below at the end of <head> block.
<style>.custom-file-label::after { content: "Choose file"; }</style>
You can also preset multi language settings and choose it by lang attribute of the input element (same way as bootstrap.css).
/* en(English) is set as default to bootstrap.css */
/* ja(Japanese) */
.custom-file-input:lang(ja) ~ .custom-file-label::after {
content: "ファイル選択";
}
/* es(Spanish) */
.custom-file-input:lang(es) ~ .custom-file-label::after {
content: "Elegir";
}
Live examples (en/ja/es)
A file browser hides the default input (by setting opaticy: 0; ) and display the filename with another label (Choose file...). It is not automatically updated when the user selects a file. JavaScript is needed to update file displays. See the code examples below (code based on jQuery is used in this page).
// DOM example
(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 example
$('#custom-file').on('change', function(event) {
$('[for="custom-file"]').text($(this).prop('files')[0].name);
});