Bootstrap 4 tutorial

Components (5): Forms



Basic example
We'll never share your email with anyone else.

Form controls

Set .form-control to input controls ( input, select, textarea ) ⇒ displays with a rounded border by 100% width

With input +attribute type="(text|email|password|number|...)"

Browser default input +attribute type="email"

input.form-control +attribute type="email"

With select

Browser default select


Browser default select +attribute multiple

select.form-control +attribute multiple

With textarea

Browser default textarea


With 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

With input




With select




Range inputs

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).

Example: input.form-control +attribute type="text" value="Read-only value" readonly
(Readonly) plain text

With setting .form-control-plaintext to a form control, it hides borders and shows like a plain text but margins/paddings are preserved.

Example (below): input.form-control-plaintext +attribute type="text" value="Read-only value" readonly
Example 1
Example 2

Checkboxes and radios

Default (stacked)
Checkboxes example
Radios example

Add .form-check-inline to div.form-check

Inline checkboxes

Inline radios

Without labels

Add .position-static to input


Form groups

A control element ( input , select , textarea , etc.) and its associated label label are set inside div.form-group

Example: gray border to form , orange border to div.form-group to indicate structure
Form grid

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 row

Changing from.row to .form-row adjusts paddings (tighter and compact) for form layouts.


From the official document (orange border to .form-group to indicate structure)

Horizontal form

Horizontal form label sizing

On horizontal forms, a form control and its corresponding label should have the same 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

Column sizing

Example using Grid to set column widths.


Changing 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.

Example 1

This 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.

Example 2

An example for responsive behaviors (modified from the official document example).


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.

Example 3

Inline variation with custom form controls (modified from the official document example).

Inline forms

(form).form-inline can be used for inline (horizontal) layouts. It sets layout settings as follows.

It is similar to auto-sizing. But it is customized for using in navigation bars and can be built with simpler structure. It is responsive as default with sm breakpoint (fixed, you have to use auto-sizing if you need different behaviors).
Basic example
Example using custom forms

Help text

Use 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.

Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.

Remove .form-text for inline layouts.

Must be 8-20 characters long.

Disabled forms

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).


HTML 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.

Browser defaults

The example below shows browser default validation behaviors. Note that each behavior heavily varies among browsers (check this example for yourself with various browsers).

Bootstrap 4 styles

The example below demonstrates Bootstrap 4 style validation.

Looks good!
Please input your name.
Looks good!
Please choose a username.
Please provide a valid city.
Please provide a valid state.
Please provide a valid zip.
You must agree before submitting.

HTML markups.

Uses Bootstrap 4 CSS validation.

Needs JavaScript.

// 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 =, function(form) {
      form.addEventListener('submit', function(event) {
        if (form.checkValidity() === false) {
      }, false);
  }, false);
// jQuery version
$('.needs-validation').on('submit', function(event) {
  if (!this.checkValidity()) {
Server-side validation

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.

The example below is showing First name and Last name are valid but all others are invalid.

Looks good!
Looks good!
Please choose a username.
Please provide a valid city.
Please provide a valid state.
Please provide a valid zip.
You must agree before submitting.
Using custom form controls

Bootstrap 4 validation supports custom form controls. The example below demonstrates validation behaviors of supported custom form controls.

Please enter a message in the textarea.
Example invalid feedback text
More example invalid feedback text
Example invalid custom select feedback
Example invalid custom file feedback

Changing from .(valid|invalid)-feedback to .(valid|invalid)-tooltip displays a validation feedback message as a tooltip popup with translucent background.

Looks good!
Looks good!
Please choose a unique and valid username.
Please provide a valid city.
Please provide a valid state.
Please provide a valid zip.

Custom form controls

Bootstrap 4 custom form controls can be used for further display customization and cross browser consistency.


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);
Radios (inline)
Select menu




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.

Set range with min and max, value with value.

Set step with step.

File browser

Translating or customizing the strings

You can change the file browser's default text (Browse on the right) to the arbitrary string.

Translating or customizing the strings with HTML

(≥ 4.2) Adding data-browse="{String}" to label.custom-file-label changes the string: English(en), Japanese(ja), and Spanish(es) examples below.

Translating or customizing the strings with SCSS

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.

Translating or customizing the strings with custom CSS

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)

Updating the filename (with JavaScript)

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 =[0].name;
    }, false);
  }, false);
// jQuery example
$('#custom-file').on('change', function(event) {