Forms overview

Use forms to allow users to enter data, submit inquiries, change settings, find information, or generally complete other tasks. When designing forms, aim to collect as little information as possible through a limited number of steps.

Best practices

  • Ask for as little information as possible. This typically includes single line text inputs for name and email and a multi-line text field for a longer message or inquiry. If additional information is required, be sure to include copy that explains why.
  • If form fields aren’t required, don’t include them in the form.
  • Choose a button label that describes the action (e.g. ‘Submit request’ or ‘Send message’).
  • Include a success message that clearly communicates what happens next and how long the user can expect to wait for a reply.
  • Auto focus on the first input field in the form. This saves time and effort and moves the user directly to the first field.
  • If a longer form is necessary, consider breaking the process into steps.
  • Investigate CAPTCHA alternatives.
  • For form-specific best practices, please refer to the form templates.

Columns

Use single-column forms wherever possible. Multi-column forms may lead to confusion and can result in users skipping fields and inputting data in the wrong field. In some scenarios, it’s OK to include more than one field in a row, but this should only be done when the data requested by each field are related or understood by the user to be part of the same set. Examples where this is acceptable include ‘city + province + postal code’ and ‘credit card number + expiry + CVV’. If you aren’t sure, always default to a new line for each form field.

Form with buttons left aligned

Do: Default to a single column layout

Form with buttons right aligned

Don't: Use a multi-column layout

Field width

Field widths should always match the length of the expected input and should rarely exceed 400px.

Do: Ensure field length matches data length

Don't: Use fields that are too long for the expected data

Titles

Use the title to describe the form. If the form is the main item on a page, use an h1, otherwise, use h2 or h3 and adjust the rest of the page hierarchy accordingly. Where possible, follow the form title with a brief description.

Fieldsets

Use fieldsets and labels (legend tags) to group and describe a set of controls and/or fields within a form.

Buttons

Use a primary button for the main action, and a link button to cancel if applicable.

Labels

Labels should be written in sentence case and always indicate what sort of information the input requires.

Helper text

Helper text gives context about an input. It’s best to provide an example here, rather than as placeholder text so that it’s visible after the text has been entered (specific to text fields). Only use helper text where clarification is required, and try not to overuse it. Standard helper text alignment is close beneath the form input.

Error messages

Error messages display instructions on how to correct data that hasn’t been accepted. Error messages are displayed below the input line, replacing helper text until fixed. Wherever possible, consider using dynamic validation that detects errors and provides feedback as data is entered.

Validation icons

Validation icons help indicate what state the field has. This includes feedback (warning, error, success, etc) or utility (more info, show/hide password, clear).

Dropdown icons indicate that a selection should be made from a larger list within a select dropdown.

Required and optional inputs

Wherever possible, only include form inputs that are absolutely necessary; ‘shorter is better’ should be the approach when it comes to form design. If you decide to add optional inputs, these fields should be marked with ‘Optional’ in parentheses above and to the right of the label. Labelling required form inputs with an asterisk is not recommended as this pattern isn’t as obvious or accessible as including ‘(Optional)’ along with the input label.

Do: Add an ‘optional’ label to optional fields

Don't: Add an asterisk or otherwise mark required fields

Multi-step forms

Breaking large forms into multiple steps reduces friction (both real and perceived), creates a manageable first impression, and provides an opportunity to show progress.

Try and limit the number of inputs per step with 5 +/- 2 as your guide. Each step should inform the user about the progress they are making (step x of x) and should have a theme that’s easy to identify and understand.

Button alignment

When using buttons to help a user move through a series of stepped screens, right-align the primary button to visually support the intended direction. The previous (secondary) button should be right-aligned, but to the left of the primary button (again, to visually support the intended direction).

<div class="row mt-4">
  <div class="col">
    <button class="btn btn-outline-secondary float-right">Previous</button>
  </div>
  <div class="col-auto">
    <button class="btn btn-primary">Next</button>
  </div>
</div>

Development overview

Bootstrap’s form controls expand on Rebooted form styles with classes. Use these classes to opt into their customized displays for a more consistent rendering across browsers and devices.

Be sure to use an appropriate type attribute on all inputs (e.g., email for email address or number for numerical information) to take advantage of newer input controls like email verification, number selection, and more.

For even more customization and cross browser consistency, we are using Bootstrap’s custom form components to replace the browser defaults. They’re built on top of semantic and accessible markup, so they’re solid replacements for any default form control. We are using custom selects, ranges, radio buttons, checkboxes and switches. We are using the default file inputs, rather than the custom ones, because of custom styling limitations and external JavaScript dependencies.

Layout

Since Bootstrap applies display: block and width: 100% to almost all our form controls, forms will by default stack vertically. Additional classes can be used to vary this layout on a per-form basis.

Form groups

The .form-group class is the easiest way to add some structure to forms. It provides a flexible class that encourages proper grouping of labels, controls, optional help text, and form validation messaging. By default it only applies margin-bottom, but it picks up additional styles in .form-inline as needed. Use it with <fieldset>s, <div>s, or nearly any other element.

<form>
  <div class="form-group">
    <label for="formGroupExampleInput">Example label</label>
    <input type="text" class="form-control" id="formGroupExampleInput">
  </div>
  <div class="form-group">
    <label for="formGroupExampleInput2">Another label</label>
    <input type="text" class="form-control" id="formGroupExampleInput2">
  </div>
</form>

Form grid

More complex forms can be built using our grid classes. Use these for form layouts that require multiple columns, varied widths, and additional alignment options.

<form>
  <div class="row">
    <div class="col">
      <label for="example1">Example label</label>
      <input id="example1" type="text" class="form-control">
    </div>
    <div class="col">
      <label for="example2">Another example input</label>
      <input id="example2" type="text" class="form-control">
    </div>
  </div>
</form>

Form row

You may also swap .row for .form-row, a variation of our standard grid row that overrides the default column gutters for tighter and more compact layouts.

<form>
  <div class="form-row">
    <div class="col">
      <label for="example3">Example label</label>
      <input id="example3" type="text" class="form-control">
    </div>
    <div class="col">
      <label for="example4">Another example input</label>
      <input id="example4" type="text" class="form-control">
    </div>
  </div>
</form>

Column sizing

As shown in the previous examples, our grid system allows you to place any number of .cols within a .row or .form-row. They’ll split the available width equally between them. You may also pick a subset of your columns to take up more or less space, while the remaining .cols equally split the rest, with specific column classes like .col-7.

<form>
  <div class="form-row">
    <div class="col-sm-5">
      <div class="form-group">
        <label for="example5">Example label</label>
        <input id="example5" type="text" class="form-control">
      </div>
    </div>
    <div class="col">
      <div class="form-group">
        <label for="example6">Another label</label>
        <input id="example6" type="text" class="form-control">
      </div>
    </div>
    <div class="col">
      <div class="form-group">
        <label for="example7">And one more</label>
        <input id="example7" type="text" class="form-control">
      </div>
    </div>
  </div>
</form>

Auto-sizing

The example below uses a flexbox utility to vertically centre the contents and changes .col to .col-auto so that your columns only take up as much space as needed. Put another way, the column sizes itself based on the contents.

@
<form>
  <div class="form-row align-items-center">
    <div class="col-auto">
      <label for="inlineFormInput">Name</label>
      <input type="text" class="form-control mb-2" id="inlineFormInput">
    </div>
    <div class="col-auto">
      <label for="inlineFormInputGroup">Username</label>
      <div class="input-group mb-2">
        <div class="input-group-prepend">
          <div class="input-group-text">@</div>
        </div>
        <input type="text" class="form-control" id="inlineFormInputGroup">
      </div>
    </div>
  </div>
</form>

You can then remix that once again with size-specific column classes.

@
<form>
  <div class="form-row align-items-center">
    <div class="col-sm-6 my-1">
      <label for="inlineFormInput2">Name</label>
      <input type="text" class="form-control mb-2" id="inlineFormInput2">
    </div>
    <div class="col-auto">
      <label for="inlineFormInputGroup2">Username</label>
      <div class="input-group mb-2">
        <div class="input-group-prepend">
          <div class="input-group-text">@</div>
        </div>
        <input type="text" class="form-control" id="inlineFormInputGroup2">
      </div>
    </div>
  </div>
</form>

Inline forms

Use the .form-inline class to display a series of labels, form controls, and buttons on a single horizontal row. Form controls within inline forms vary slightly from their default states.

  • Controls are display: flex, collapsing any HTML white space and allowing you to provide alignment control with spacing and flexbox utilities.
  • Controls and input groups receive width: auto to override the Bootstrap default width: 100%.
  • Controls only appear inline in viewports that are at least 576px wide to account for narrow viewports on mobile devices.

You may need to manually address the width and alignment of individual form controls with spacing utilities (as shown below). Lastly, be sure to always include a <label> with each form control, even if you need to hide it from non-screenreader visitors with .sr-only.

<form class="form-inline">
  <label class="my-1 mr-2" for="inlineFormCustomSelectPref">Preference</label>
  <select class="custom-select my-1 mr-sm-3" id="inlineFormCustomSelectPref">
    <option selected>Choose...</option>
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
  </select>
  <div class="custom-control custom-checkbox my-1 mr-3">
    <input type="checkbox" class="custom-control-input" id="customControlInline">
    <label class="custom-control-label" for="customControlInline">Remember my preference</label>
  </div>
  <button type="submit" class="btn btn-primary my-1">Submit</button>
</form>
Alternatives to hidden labels

Assistive technologies such as screen readers will have trouble with your forms if you don’t include a label for every input. For these inline forms, you can hide the labels using the .sr-only class. There are further alternative methods of providing a label for assistive technologies, such as the aria-label, aria-labelledby or title attribute. If none of these are present, assistive technologies may resort to using the placeholder attribute, if present, but note that use of placeholder as a replacement for other labelling methods is not advised.

Help text

Helper text gives context about an input. It’s best to provide an example here, rather than as placeholder text so that it’s visible after the text has been entered (specific to text fields). Only use helper text where clarification is required, and try not to overuse it.

Block-level help text in forms can be created using .form-text (previously known as .help-block in v3). Inline help text can be flexibly implemented using any inline HTML element and utility classes like .text-muted.

Associating help text with form controls

Help text should be explicitly associated with the form control it relates to using the aria-describedby attribute. This will ensure that assistive technologies—such as screen readers—will announce this help text when the user focuses or enters the control.

Help text below inputs can be styled with .form-text. This class includes display: block and adds some top margin for easy spacing from the inputs above.

Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.
<label for="inputPassword5">Password</label>
<input type="password" id="inputPassword5" class="form-control" aria-describedby="passwordHelpBlock">
<small id="passwordHelpBlock" class="form-text text-muted">
  Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.
</small>

Inline text can use any typical inline HTML element (be it a <small>, <span>, or something else) with nothing more than a utility class.

Must be 8-20 characters long.
<form class="form-inline">
  <div class="form-group">
    <label for="inputPassword6">Password</label>
    <input type="password" id="inputPassword6" class="form-control mx-sm-3" aria-describedby="passwordHelpInline">
    <small id="passwordHelpInline" class="text-muted">
      Must be 8-20 characters long.
    </small>
  </div>
</form>

Disabled forms

Add the disabled boolean attribute on an <input> or <fieldset> to prevent user interactions and make it appear lighter.

<label for="disabledInput">Disabled input</label>
<input class="form-control" id="disabledInput" type="text" disabled>
Caveat with anchors

By default, browsers will treat all native form controls (<input>, <select> and <button> elements) inside a <fieldset disabled> as disabled, preventing both keyboard and mouse interactions on them. However, if your form also includes <a ... class="btn btn-*"> elements, these will only be given a style of pointer-events: none. As noted in the section about disabled state for buttons (and specifically in the sub-section for anchor elements), this CSS property is not yet standardized and isn’t fully supported in Internet Explorer 10, and won’t prevent keyboard users from being able to focus or activate these links. So to be safe, use custom JavaScript to disable such links.

Cross-browser compatibility

While Bootstrap will apply these styles in all browsers, Internet Explorer 11 and below don’t fully support the disabled attribute on a <fieldset>. Use custom JavaScript to disable the fieldset in these browsers.