Forms
v1.0.0Native controls with consistent labels, spacing, validation and actions.
Overview
Forms style native inputs, selects, choices, range sliders and switches. See their pages for details.
Range Slider
Use .range-slider-input for native range inputs with a custom track and thumb.
View range sliderBasic structure
Use .form-label with the matching control class.
<div class="mb-3">
<label class="form-label" for="email">E-Mail</label>
<input class="form-control" id="email" name="email" type="email" placeholder="your email" />
</div>
Required fields
Use native required and mark its label with .is-required.
<div class="mb-3">
<label class="form-label is-required" for="fullname">Fullname</label>
<input class="form-control" id="fullname" name="fullname" required />
</div>
Validation
Combine .is-invalid and aria-invalid=“true”. Link .invalid-feedback with aria-describedby and its id.
<div class="mb-3">
<label class="form-label" for="invalidEmail">E-Mail</label>
<input
class="form-control is-invalid"
id="invalidEmail"
name="invalidEmail"
type="email"
aria-invalid="true"
aria-describedby="invalidEmailFeedback" />
<div class="invalid-feedback" id="invalidEmailFeedback">
Please enter a valid email address.
</div>
</div>
Extended form example
<form>
<div class="mb-3">
<label for="salutation" class="form-label">Salutation</label>
<select class="form-select" id="salutation" name="salutation">
<option value="not-specified">not specified</option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
<div class="mb-3">
<label for="fullname" class="form-label is-required">Fullname</label>
<input
class="form-control"
id="fullname"
name="fullname"
required
placeholder="your fullname" />
</div>
<div class="mb-3">
<label for="birthdate" class="form-label">Birthdate</label>
<input class="form-control" id="birthdate" name="birthdate" type="date" />
</div>
<div class="mb-3">
<label for="email" class="form-label is-required">E-Mail</label>
<input
class="form-control"
id="email"
name="email"
type="email"
pattern="[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}$"
required
placeholder="your email" />
</div>
<div class="mb-3">
<label for="message" class="form-label">Note / Message</label>
<textarea
class="form-control"
id="message"
name="message"
placeholder="your message"></textarea>
</div>
<fieldset class="border border-0 min-w-0 mb-3">
<legend class="mb-2">Notification type</legend>
<div class="d-flex flex-column gap-2">
<div class="form-check">
<input
class="form-check-input"
id="notificationEmail"
name="notificationType"
type="radio"
value="email"
checked />
<label class="form-label" for="notificationEmail">E-Mail</label>
</div>
<div class="form-check">
<input
class="form-check-input"
id="notificationSms"
name="notificationType"
type="radio"
value="sms" />
<label class="form-label" for="notificationSms">SMS</label>
</div>
</div>
</fieldset>
<div class="form-switch mb-3">
<input
class="form-switch-input"
id="notifications"
name="notifications"
type="checkbox"
checked />
<label class="form-label" for="notifications">Enable notifications</label>
</div>
<div class="range-slider mb-3">
<div class="range-slider-header">
<label class="form-label" for="digestLimit">Daily digest limit</label>
<output class="range-slider-output" for="digestLimit">8 items</output>
</div>
<input
class="range-slider-input"
id="digestLimit"
name="digestLimit"
type="range"
min="1"
max="20"
value="8"
style="--range-slider-progress: 36.84%" />
<div class="range-slider-marks" aria-hidden="true">
<span>1</span>
<span>20</span>
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" name="privacy" id="privacy" type="checkbox" required />
<label class="form-label is-required" for="privacy">I have read the data policy</label>
</div>
<div class="d-flex gap-1">
<button id="btnCancel" type="button" class="btn btn-secondary btn-text">cancel</button>
<button id="btnSubmit" class="btn btn-primary btn-solid" type="submit">submit</button>
</div>
</form>
CSS Variables
Override these variables on the component or an ancestor.
--form-control-bg-color: var(--bg-surface);
--form-control-border-width: var(--border-width);
--form-control-border-color: var(--control-border-color);
--form-control-border-radius: var(--border-radius);
--form-control-padding-y: var(--spacer-1);
--form-control-padding-x: var(--spacer-3);
--form-control-font-size: var(--font-size);
--form-control-font-weight: 400;
--form-control-placeholder-color: var(--text-subtle);
--form-control-disabled-text-color: var(--disabled-text-color);
--form-control-disabled-bg-color: var(--disabled-bg-color);
--form-control-disabled-border-color: var(--disabled-border-color);
--form-control-focus-border-color: var(--primary-hover);
--form-control-focus-outline-width: var(--focus-outline-width);
--form-control-focus-outline-style: var(--focus-outline-style);
--form-control-focus-outline-color: var(--focus-outline-color);
--form-control-focus-outline-offset: var(--focus-offset);
--form-control-transition-duration: var(--transition-duration);
--form-control-transition-easing: var(--transition-easing);
--form-select-bg-color: var(--bg-surface);
--form-select-border-width: var(--border-width);
--form-select-border-color: var(--control-border-color);
--form-select-border-radius: var(--border-radius);
--form-select-padding-y: var(--spacer-1);
--form-select-padding-x: var(--spacer-3);
--form-select-indicator-padding: var(--spacer-5);
--form-select-font-size: var(--font-size);
--form-select-font-weight: 400;
--form-select-disabled-text-color: var(--disabled-text-color);
--form-select-disabled-bg-color: var(--disabled-bg-color);
--form-select-disabled-border-color: var(--disabled-border-color);
--form-select-focus-border-color: var(--primary-hover);
--form-select-focus-outline-width: var(--focus-outline-width);
--form-select-focus-outline-style: var(--focus-outline-style);
--form-select-focus-outline-color: var(--focus-outline-color);
--form-select-focus-outline-offset: var(--focus-offset);
--form-select-transition-duration: var(--transition-duration);
--form-select-transition-easing: var(--transition-easing);
--form-check-gap: var(--spacer-2);
--form-check-input-size: 1rem;
--form-check-input-border-radius: var(--border-radius-sm, 0.25rem);
--form-check-input-bg-color: var(--bg-surface);
--form-check-input-border-width: var(--border-width);
--form-check-input-border-color: var(--control-border-color);
--form-check-input-checked-bg-color: var(--primary);
--form-check-input-checked-border-color: var(--primary);
--form-check-input-checked-color: var(--on-primary);
--form-check-disabled-bg-color: var(--disabled-bg-color);
--form-check-disabled-border-color: var(--disabled-border-color);
--form-check-transition-duration: var(--transition-duration);
--form-check-transition-easing: var(--transition-easing);
--form-switch-gap: var(--spacer-2);
--form-switch-input-width: 2.5rem;
--form-switch-input-height: 1.25rem;
--form-switch-input-padding: 0.125rem;
--form-switch-input-bg-color: var(--bg-highlight);
--form-switch-input-border-width: var(--border-width);
--form-switch-input-border-color: var(--control-border-color);
--form-switch-input-border-radius: 9999px;
--form-switch-input-checked-bg-color: var(--primary);
--form-switch-input-checked-border-color: var(--primary);
--form-switch-thumb-size: 1rem;
--form-switch-thumb-bg-color: var(--bg-surface);
--form-switch-thumb-box-shadow: var(--shadow-sm);
--form-switch-thumb-checked-translate-x: calc(
var(--form-switch-input-width) - var(--form-switch-thumb-size) -
(var(--form-switch-input-padding) * 2) - (var(--form-switch-input-border-width) * 2)
);
--form-switch-disabled-bg-color: var(--disabled-bg-color);
--form-switch-disabled-border-color: var(--disabled-border-color);
--form-switch-disabled-thumb-bg-color: var(--disabled-text-color);
--form-switch-focus-outline-width: var(--focus-outline-width);
--form-switch-focus-outline-style: var(--focus-outline-style);
--form-switch-focus-outline-color: var(--focus-outline-color);
--form-switch-focus-outline-offset: var(--focus-offset);
--form-switch-transition-duration: var(--transition-duration);
--form-switch-transition-easing: var(--transition-easing);