Checkboxes, radio buttons and sliders are notoriously inconsistent across browsers. Bootstrap replaces their native look with SVG-based controls that match the rest of the framework while keeping the underlying HTML elements, so keyboard support, form submission and validation work exactly as before. This lesson covers the .form-check family, switches, inline and reversed layouts, toggle buttons built on .btn-check, and the .form-range slider.
The markup is a wrapper, an input and a label:
<div class="form-check">
<input class="form-check-input" type="checkbox" value="yes" id="terms">
<label class="form-check-label" for="terms">I agree to the terms</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="plan" id="plan-free" value="free" checked>
<label class="form-check-label" for="plan-free">Free</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="plan" id="plan-pro" value="pro">
<label class="form-check-label" for="plan-pro">Pro</label>
</div>.form-check sets up the padding and positions the input to the left of the label..form-check-input draws the custom box or circle; type decides which.name; wrap the group in a <fieldset> with a <legend> so its purpose is announced.Add disabled to the input and Bootstrap greys the label automatically. Add indeterminate via JavaScript (input.indeterminate = true) to show the dash state used by "select all" checkboxes.
A switch is a checkbox with .form-switch on the wrapper and role="switch" on the input:
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="dark" >
<label class="form-check-label" for="dark">Dark mode</label>
</div>Use switches for settings that take effect immediately; use checkboxes for options that are submitted with a form.
| Variant | Class | Effect |
|---|---|---|
| Inline | .form-check-inline | Multiple checks on one line |
| Reverse | .form-check-reverse | Label on the left, control on the right |
| No label | omit .form-check wrapper, add aria-label | Bare control for table rows |
<div class="form-check form-check-reverse">
<input class="form-check-input" type="checkbox" id="remember">
<label class="form-check-label" for="remember">Remember me</label>
</div>
<td><input class="form-check-input" type="checkbox" aria-label="Select row 3"></td>btn-checkCheckboxes and radios can look like buttons. Hide the input with .btn-check and style the label as a .btn:
<input type="checkbox" class="btn-check" id="bold" autocomplete="off">
<label class="btn btn-outline-primary" for="bold">Bold</label>
<div class="btn-group" role="group" aria-label="Alignment">
<input type="radio" class="btn-check" name="align" id="left" autocomplete="off" checked>
<label class="btn btn-outline-secondary" for="left">Left</label>
<input type="radio" class="btn-check" name="align" id="center" autocomplete="off">
<label class="btn btn-outline-secondary" for="center">Center</label>
</div>autocomplete="off" stops Firefox from restoring the checked state after a reload. Because these are real inputs, the values are submitted with the form and the checked state is fully keyboard accessible, unlike JavaScript-toggled .active buttons.
.form-range styles <input type="range"> with a consistent track and thumb:
<label for="volume" class="form-label">Volume</label>
<input type="range" class="form-range" id="volume" min="0" max="100" step="5" value="40">min, max and step are native attributes.<output> element updated on input, as in the sample at the top.disabled greys the track and blocks interaction.const form = document.querySelector("form");
form.addEventListener("submit", (event) => {
event.preventDefault();
const data = new FormData(form);
console.log(data.get("cycle")); // "monthly" or "yearly"
console.log(data.getAll("skills")); // every checked checkbox named "skills"
console.log(data.has("notify")); // true only when the switch is on
});Unchecked checkboxes are not included in FormData, which is why has() is the right check for switches.
role="switch". Without it, screen readers announce a checkbox, not a switch.name values on radios. They stop being mutually exclusive..form-control on checks. The box will stretch to full width; checks use .form-check-input.for. Clicking the text will not toggle the control.What turns a Bootstrap checkbox into a switch?
.form-check wraps a .form-check-input and .form-check-label; type chooses checkbox or radio..form-switch plus role="switch" creates an accessible toggle; .form-check-inline and .form-check-reverse change layout..btn-check hides the input so a .btn label becomes a real, submittable toggle button..form-range styles sliders; show the value with an <output> element.FormData, so test with has().Next lesson: Floating Labels and Form Layout - animated placeholder labels, horizontal and inline forms, and grid-based form rows.