Skip to main content Skip to docs navigation

Form controls

Give textual <input>, <textarea>, and <select> elements an upgrade with custom styles, sizing, focus states, and more.

Heads up! In v6, <select> elements are styled with .form-control. This reduces duplication and abstraction while making it easier to consistently customize the appearance of form elements.

Example

Form controls are styled with a mix of Sass and CSS variables, allowing them to adapt to color modes and support any customization method.

HTML
<div>
  <label for="exampleFormControlInput1" class="form-label">Email address</label>
  <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>
<div>
  <label for="exampleFormControlSelect1" class="form-label">Example select</label>
  <select class="form-control" id="exampleFormControlSelect1">
    <option>Open this select menu</option>
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
  </select>
</div>
<div>
  <label for="exampleFormControlTextarea1" class="form-label">Example textarea</label>
  <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>

Sizes

Change the size of a form control by using classes like .form-control-lg and .form-control-sm. This adjusts height, padding, font-size, line-height, and border-radius.

HTML
<div>
  <label for="largeInput" class="form-label">Large input</label>
  <input class="form-control form-control-lg" type="text" id="largeInput" placeholder="Large input" aria-label="Large input example">
</div>
<div>
  <label for="largeSelect" class="form-label">Large select</label>
  <select class="form-control form-control-lg" id="largeSelect">
    <option>Open this select menu</option>
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
  </select>
</div>
<div>
  <label for="largeTextarea" class="form-label">Large textarea</label>
  <textarea class="form-control form-control-lg" id="largeTextarea" rows="3" placeholder="Large textarea" aria-label="Large textarea example"></textarea>
</div>
HTML
<div>
  <label for="smallInput" class="form-label">Small input</label>
  <input class="form-control form-control-sm" type="text" id="smallInput" placeholder="Small input" aria-label="Small input example">
</div>
<div>
  <label for="smallSelect" class="form-label">Small select</label>
  <select class="form-control form-control-sm" id="smallSelect">
    <option>Open this select menu</option>
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
  </select>
</div>
<div>
  <label for="smallTextarea" class="form-label">Small textarea</label>
  <textarea class="form-control form-control-sm" id="smallTextarea" rows="3" placeholder="Small textarea" aria-label="Small textarea example"></textarea>
</div>

Select

Basic select element styles are provided by the .form-control class. Styles are limited by the browser—options and popovers cannot be styled.

HTML
<select class="form-control" id="exampleFormControlSelect2">
  <option>Choose one…</option>
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>

The multiple attribute is supported on select elements:

HTML
<select class="form-select" multiple aria-label="Multiple select example">
  <option selected>Open this select menu</option>
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>

As is the size attribute:

HTML
<select class="form-select" size="3" aria-label="Size 3 select example">
  <option selected>Open this select menu</option>
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>

Form text

Block-level or inline-level form text can be created using .form-text.

Form 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 form text when the user focuses or enters the control.

Form text below inputs can be styled with .form-text. If a block-level element will be used, a top margin is added 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.
HTML
<label for="inputPassword5" class="form-label">Password</label>
<input type="password" id="inputPassword5" class="form-control" aria-describedby="passwordHelpBlock">
<div id="passwordHelpBlock" class="form-text">
  Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.
</div>

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

Must be 8-20 characters long.
HTML
<div class="row g-3 align-items-center">
  <div class="col-auto">
    <label for="inputPassword6" class="col-form-label">Password</label>
  </div>
  <div class="col-auto">
    <input type="password" id="inputPassword6" class="form-control" aria-describedby="passwordHelpInline">
  </div>
  <div class="col-auto">
    <span id="passwordHelpInline" class="form-text">
      Must be 8-20 characters long.
    </span>
  </div>
</div>

States

Disabled

Add the disabled boolean attribute on an input to give it a grayed out appearance, remove pointer events, and prevent focusing.

HTML
<input class="form-control" type="text" placeholder="Disabled input" aria-label="Disabled input example" disabled>
<input class="form-control" type="text" value="Disabled readonly input" aria-label="Disabled input example" disabled readonly>
<select class="form-control" aria-label="Disabled select example" disabled>
  <option selected>Open this select menu</option>
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>
<textarea class="form-control" rows="3" placeholder="Disabled textarea" aria-label="Disabled textarea example" disabled></textarea>

Readonly

Add the readonly boolean attribute on an input to prevent modification of the input’s value. readonly inputs can still be focused and selected, while disabled inputs cannot.

HTML
<input class="form-control" type="text" value="Readonly input here..." aria-label="readonly input example" readonly>

Readonly plain text

If you want to have <input readonly> elements in your form styled as plain text, replace .form-control with .form-control-plaintext to remove the default form field styling and preserve the correct margin and padding.

HTML
<div class="mb-3 row">
  <label for="staticEmail" class="col-sm-2 col-form-label">Email</label>
  <div class="col-sm-10">
    <input type="text" readonly class="form-control-plaintext" id="staticEmail" value="email@example.com">
  </div>
</div>
<div class="mb-3 row">
  <label for="inputPassword" class="col-sm-2 col-form-label">Password</label>
  <div class="col-sm-10">
    <input type="password" class="form-control" id="inputPassword">
  </div>
</div>
HTML
<form class="row g-3">
  <div class="col-auto">
    <label for="staticEmail2" class="visually-hidden">Email</label>
    <input type="text" readonly class="form-control-plaintext" id="staticEmail2" value="email@example.com">
  </div>
  <div class="col-auto">
    <label for="inputPassword2" class="visually-hidden">Password</label>
    <input type="password" class="form-control" id="inputPassword2" placeholder="Password">
  </div>
  <div class="col-auto">
    <button type="submit" class="btn btn-primary mb-3">Confirm identity</button>
  </div>
</form>

Types

Nearly all input types are supported, but not all are documented here. Input types requiring additional classes or changes are shown below.

Color

Set the type="color" and add .form-control-color to the <input> alongside .form-control. We use the modifier class to set fixed heights and override some inconsistencies between browsers.

HTML
<label for="exampleColorInput" class="form-label">Color picker</label>
<input type="color" class="form-control form-control-color" id="exampleColorInput" value="#631aff" title="Choose your color">

Sizes are also supported:

HTML
<div>
  <label for="exampleColorInputLg" class="form-label">Large color picker</label>
  <input type="color" class="form-control form-control-lg form-control-color" id="exampleColorInputLg" value="#631aff" title="Choose your color">
</div>
<div>
  <label for="exampleColorInputSm" class="form-label">Small color picker</label>
  <input type="color" class="form-control form-control-sm form-control-color" id="exampleColorInputSm" value="#631aff" title="Choose your color">
</div>

Datalists

Datalists allow you to create a group of <option>s that can be accessed (and autocompleted) from within an <input>. These are similar to <select> elements, but come with more menu styling limitations and differences. While most browsers and operating systems include some support for <datalist> elements, their styling is inconsistent at best.

Learn more about support for datalist elements.

HTML
<label for="exampleDataList" class="form-label">Datalist example</label>
<input class="form-control" list="datalistOptions" id="exampleDataList" placeholder="Type to search...">
<datalist id="datalistOptions">
  <option value="San Francisco">
  <option value="New York">
  <option value="Seattle">
  <option value="Los Angeles">
  <option value="Chicago">
</datalist>

Date & time

No additional classes are needed for date and time inputs.

HTML
<label for="exampleDateTimeInput" class="form-label">Date and time picker</label>
<input type="datetime-local" class="form-control" id="exampleDateTimeInput" value="2026-02-24T13:00">
HTML
<label for="exampleDateInput" class="form-label">Date picker</label>
<input type="date" class="form-control" id="exampleDateInput" value="2026-02-24">
HTML
<label for="exampleTimeInput" class="form-label">Time picker</label>
<input type="time" class="form-control" id="exampleTimeInput" value="13:00">

File

input[type="file"] elements are styled with the ::file-selector-button pseudo element to add a button to the input. You only need to add the .form-control class, plus any size modifiers you need.

HTML
<div class="mb-3">
  <label for="formFile" class="form-label">Default file input example</label>
  <input class="form-control" type="file" id="formFile">
</div>
<div class="mb-3">
  <label for="formFileMultiple" class="form-label">Multiple files input example</label>
  <input class="form-control" type="file" id="formFileMultiple" multiple>
</div>
<div class="mb-3">
  <label for="formFileDisabled" class="form-label">Disabled file input example</label>
  <input class="form-control" type="file" id="formFileDisabled" disabled>
</div>
<div class="mb-3">
  <label for="formFileSm" class="form-label">Small file input example</label>
  <input class="form-control form-control-sm" id="formFileSm" type="file">
</div>
<div>
  <label for="formFileLg" class="form-label">Large file input example</label>
  <input class="form-control form-control-lg" id="formFileLg" type="file">
</div>

Ghost

Ghost inputs are a special type of input, not native to the browser, that removes all default input styling when your wrapper handles spacing, border, and focus styles. This is useful for custom composites like search bars and command inputs. Swap the .form-control class for .form-ghost to remove the default styling.

.form-ghost removes the input's own focus outline. Use :focus-within on a parent element to provide a visible focus indicator.

HTML
<label for="exampleGhostInput" class="form-label">Search</label>
<div class="d-flex align-items-center gap-2 p-2 border rounded">
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" aria-hidden="true" viewBox="0 0 16 16">
    <path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/>
  </svg>
  <input type="search" class="form-ghost" id="exampleGhostInput" placeholder="Search docs" aria-label="Search docs">
</div>

CSS

Variables

Form controls use local CSS variables on .form-control for real-time customization. Values for the CSS variables are generated from Sass maps unique to each component and applied to the aforementioned class.

SCSS
// stylelint-disable custom-property-no-missing-var-function
// stylelint-disable-next-line scss/dollar-variable-default
$form-control-tokens: defaults(
  (
    --control-min-height: var(--btn-input-min-height),
    --control-padding-y: var(--btn-input-padding-y),
    --control-padding-x: var(--btn-input-padding-x),
    --control-font-size: var(--btn-input-font-size),
    --control-line-height: var(--btn-input-line-height),
    --control-fg: var(--btn-input-fg),
    --control-bg: var(--btn-input-bg),
    --control-border-width: var(--border-width),
    --control-border-color: var(--border-color),
    --control-border-radius: var(--border-radius),
    --control-box-shadow: var(--box-shadow-inset),
    --control-action-bg: var(--bg-1),
    --control-action-hover-bg: var(--bg-2),
    --control-transition-property: "border-color, box-shadow",
    --control-transition-timing: .15s ease-in-out,
    --control-transition: var(--control-transition-property) var(--control-transition-timing),
    --control-placeholder-color: var(--fg-3),
    --control-disabled-color: var(--control-fg),
    --control-disabled-bg: var(--bg-2),
    --control-disabled-border-color: var(--control-border-color),
    --control-select-bg: #{escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='#00000080' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>"))},
    --control-select-bg-position: right .75rem center,
    --control-select-bg-size: 16px 12px,
    --control-select-bg-dark: #{escape-svg(url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='none' stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>"))},
  ),
  $form-control-tokens
);

And for .form-label:

SCSS
// stylelint-disable-next-line scss/dollar-variable-default
$form-label-tokens: defaults(
  (
    --label-margin-bottom: calc(var(--spacer) / 2),
    --label-font-size: null,
    --label-font-style: null,
    --label-font-weight: null,
    --label-color: null,
  ),
  $form-label-tokens
);

And for .form-text:

SCSS
// stylelint-disable-next-line scss/dollar-variable-default
$form-text-tokens: defaults(
  (
    --form-text-margin-top: .25rem,
    --form-text-font-size: var(--font-size-sm),
    --form-text-font-style: null,
    --form-text-font-weight: null,
    --form-text-color: var(--fg-3),
  ),
  $form-text-tokens
);

Root variables

Some inputs and buttons share some root variables for consistency across all form elements, primarily for sizing.

SCSS
--control-checked-bg: var(--primary-base),
--control-checked-border-color: var(--control-checked-bg),
--control-active-bg: var(--primary-base),
--control-active-border-color: var(--control-active-bg),
--control-disabled-bg: var(--bg-3),
--control-disabled-opacity: .65,

--btn-input-fg: var(--fg-body),
--btn-input-bg: var(--bg-body),

--btn-input-min-height: 2.5rem,
--btn-input-padding-y: .375rem,
--btn-input-padding-x: .75rem,
--btn-input-font-size: var(--font-size-base),
--btn-input-line-height: var(--line-height-base),
--btn-input-border-radius: var(--border-radius),

--btn-input-xs-min-height: 1.5rem,
--btn-input-xs-padding-y: .125rem,
--btn-input-xs-padding-x: .5rem,
--btn-input-xs-font-size: var(--font-size-xs),
--btn-input-xs-line-height: 1.125,
--btn-input-xs-border-radius: var(--border-radius-xs),

--btn-input-sm-min-height: 2.25rem,
--btn-input-sm-padding-y: .25rem,
--btn-input-sm-padding-x: .625rem,
--btn-input-sm-font-size: var(--font-size-sm),
--btn-input-sm-line-height: var(--line-height-sm),
--btn-input-sm-border-radius: var(--border-radius-sm),

--btn-input-lg-min-height: 3rem,
--btn-input-lg-padding-y: .5rem,
--btn-input-lg-padding-x: 1rem,
--btn-input-lg-font-size: var(--font-size-md),
--btn-input-lg-line-height: var(--line-height-md),
--btn-input-lg-border-radius: var(--border-radius-lg),

Sass maps

We use a Sass map to define the sizes of the form controls, so you can easily add or modify sizes.

SCSS
$form-control-sizes: ();
// stylelint-disable-next-line scss/dollar-variable-default
$form-control-sizes: defaults(
  ("sm", "lg"),
  $form-control-sizes
);