Examples and usage guidelines for form control styles, layout options, and custom components for creating a wide variety of forms.

Overview

Boosted’s form controls expand on our 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.

Here’s a quick example to demonstrate Boosted’s form styles. Keep reading for documentation on required classes, form layout, and more.

We'll never share your email with anyone else.
html
<form>
  <div class="mb-3">
    <label for="exampleInputEmail1" class="form-label">Email address</label>
    <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
    <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
  </div>
  <div class="mb-3">
    <label for="exampleInputPassword1" class="form-label">Password</label>
    <input type="password" class="form-control" id="exampleInputPassword1">
  </div>
  <div class="mb-3 form-check">
    <input type="checkbox" class="form-check-input" id="exampleCheck1">
    <label class="form-check-label" for="exampleCheck1">Check me out</label>
  </div>
  <button type="submit" class="btn btn-primary mt-2">Submit</button>
</form>

Disabled forms

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

<input class="form-control" id="disabledInput" type="text" placeholder="Disabled input here..." disabled>

Add the disabled attribute to a <fieldset> to disable all the controls within. Browsers 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 custom button-like elements such as <a class="btn btn-*">...</a>, these will only be given a style of pointer-events: none, meaning they are still focusable and operable using the keyboard. In this case, you must manually modify these controls by adding tabindex="-1" to prevent them from receiving focus and aria-disabled="disabled" to signal their state to assistive technologies.

Use the .is-disabled class on label to make it appear lighter too.

Disabled fieldset example
html
<form>
  <fieldset disabled>
    <legend>Disabled fieldset example</legend>
    <div class="mb-3">
      <label for="disabledTextInput" class="form-label is-disabled">Disabled input</label>
      <input type="text" id="disabledTextInput" class="form-control" placeholder="Disabled input">
    </div>
    <div class="mb-3">
      <label for="disabledSelect" class="form-label is-disabled">Disabled select menu</label>
      <select id="disabledSelect" class="form-select">
        <option>Disabled select</option>
      </select>
    </div>
    <div class="mb-3">
      <div class="form-check">
        <input class="form-check-input" type="checkbox" id="disabledFieldsetCheck" disabled>
        <label class="form-check-label" for="disabledFieldsetCheck">
          Can't check this
        </label>
      </div>
    </div>
    <button type="submit" class="btn btn-primary mt-2">Submit</button>
  </fieldset>
</form>

Required field

Use the .is-required class on label to add a * symbol after it.

The * symbol is actually inserted via CSS in a ::after pseudo-element. Unfortunately CSS generated content is not well supported by all assistive technologies and/or browsers. That is why mandatory input fields require an additional <span class="visually-hidden"> (required)</span> element added inside corresponding labels to ensure correct restitution by assistive technologies like screen readers.
html
<form>
  <fieldset>
    <div class="mb-3">
      <label for="requiredTextInput" class="form-label is-required">Required input<span class="visually-hidden"> (required)</span></label>
      <input type="text" id="requiredTextInput" class="form-control" placeholder="Required input" required>
    </div>
    <div class="mb-3">
      <label for="requiredSelect" class="form-label is-required">Required select menu<span class="visually-hidden"> (required)</span></label>
      <select id="requiredSelect" class="form-select" required>
        <option value="">Required select</option>
      </select>
    </div>
    <div class="mb-3">
      <div class="form-check">
        <input class="form-check-input" type="checkbox" id="requiredFieldsetCheck" required>
        <label class="form-check-label" for="requiredFieldsetCheck">Must check this<span class="visually-hidden"> (required)</span></label>
      </div>
    </div>
    <button type="submit" class="btn btn-primary mt-2">Submit</button>
  </fieldset>
</form>

Form helper

Form helper is a button using .form-helper that provides extra help information to a form control. Be sure to include text for screen readers with a visually hidden text.

Depending on the extra help information content, choose wisely between triggering a popover or a tooltip. Tooltips should be used for small and simple texts without any actionable elements inside, while popovers are used in other cases.

This form helper should be displayed right after the label.

html
<div class="mb-3">
  <label for="tooltipTextInput" class="form-label">Input with helper inside a Popover</label>
  <button type="button" class="form-helper" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Help for input">
    <span class="visually-hidden">Helper for input</span>
  </button>
  <input type="text" id="tooltipTextInput" class="form-control" placeholder="Tooltip input">
</div>
<div>
  <label for="tooltipSelect" class="form-label is-required mt-3">Select menu with helper inside a Tooltip<span class="visually-hidden"> (required)</span></label>
  <button type="button" class="form-helper" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Help for select menu">
    <span class="visually-hidden">Helper for select menu</span>
  </button>
  <select id="tooltipSelect" class="form-select" required>
    <option value="">Tooltip select</option>
  </select>
</div>

Accessibility

Ensure that all form controls have an appropriate accessible name so that their purpose can be conveyed to users of assistive technologies. The simplest way to achieve this is to use a <label> element, or—in the case of buttons—to include sufficiently descriptive text as part of the <button>...</button> content.

For situations where it’s not possible to include a visible <label> or appropriate text content, there are alternative ways of still providing an accessible name, such as:

  • <label> elements hidden using the .visually-hidden class
  • Pointing to an existing element that can act as a label using aria-labelledby
  • Providing a title attribute
  • Explicitly setting the accessible name on an element using aria-label

If none of these are present, assistive technologies may resort to using the placeholder attribute as a fallback for the accessible name on <input> and <textarea> elements. The examples in this section provide a few suggested, case-specific approaches.

While using visually hidden content (.visually-hidden, aria-label, and even placeholder content, which disappears once a form field has content) will benefit assistive technology users, a lack of visible label text may still be problematic for certain users. Some form of visible label is generally the best approach, both for accessibility and usability.

CSS

Many form variables are set at a general level to be re-used and extended by individual form components. You’ll see these most often as $input-btn-* and $input-* variables.

Sass variables

$input-btn-* variables are shared global variables between our buttons and our form components. You’ll find these frequently reassigned as values to other component-specific variables.

$input-btn-padding-y:         .5rem;
$input-btn-padding-x:         1.125rem;
$input-btn-font-family:       inherit;
$input-btn-font-size:         $font-size-base;
$input-btn-line-height:       1.25;

$input-btn-focus-width:       $focus-visible-outer-offset; // Boosted mod: instead of `$focus-ring-width`
// Boosted mod: no `$input-btn-focus-color-opacity`
// Boosted mod: no `$input-btn-focus-color`
// Boosted mod: no `$input-btn-focus-blur`
$input-btn-focus-box-shadow:  $focus-ring-box-shadow;

$input-btn-padding-y-sm:      $spacer * .25;
$input-btn-padding-x-sm:      $spacer * .5;
$input-btn-font-size-sm:      $font-size-sm;

$input-btn-padding-y-lg:      .8125rem;
$input-btn-padding-x-lg:      $spacer;
$input-btn-font-size-lg:      $font-size-lg;

$input-btn-border-width:      var(--#{$prefix}border-width);

Variables for all form helpers:

$form-helper-size:                      1.25rem; // Boosted mod
$form-helper-color:                     var(--#{$prefix}info); // Boosted mod
$form-helper-bg:                        var(--#{$prefix}highlight-color); // Boosted mod
$form-helper-icon:                      escape-svg($helper-icon); // Boosted mod
$form-helper-label-margin-bottom:       $form-label-margin-bottom - divide(($form-helper-size - $font-size-base), 2); // Boosted mod