Checkbox and radio
Consistent cross-browser and cross-device checkboxes, radio buttons, and switches.
Create amazing Typeform-like forms and pages just by writing Markdown!
Approach #
Browser default checkboxes and radio buttons are replaced with the help of a wrapping container with the .form-check
class. Inside, the <input class="form-check-input">
and <label class="form-check-label">
elements are sibling elements, as opposed to the input being inside the label. This is slightly more verbose as you must specify id
and for
attributes to relate the two. The styling is done using the sibling selector (~
).
Checkbox #
Checkboxes are used for selecting one or several options in a list. Checkboxes can be created by using type="checkbox"
. They can also be disabled using the disabled
attribute. You can read more about this element on MDN: <input type="checkbox">
(opens in new tab).
HTML
<label class="form-label">My languages are...</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-1">
<label class="form-check-label" for="example-checkbox-1">
Python
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-2" checked>
<label class="form-check-label" for="example-checkbox-2">
JavaScript
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-3" disabled>
<label class="form-check-label" for="example-checkbox-3">
C++ (disabled)
</label>
</div>
Indeterminate checkbox #
Checkboxes can utilize the :indeterminate
pseudo-class when manually set via JavaScript (there is no available HTML attribute for specifying it).
HTML
<!-- Indeterminate checkbox -->
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-4">
<label class="form-check-label" for="example-checkbox-4">
Accept all
</label>
</div>
JavaScript
/* JS to create indeterminate checkbox */
document.getElementById("example-checkbox-4").indeterminate = true;
Radio #
Radio buttons are for selecting one option from many. Radio buttons can be created by using type="radio"
. They can also be disabled using the disabled
attribute. Radio buttons with the same name
are grouped together as one input. You can read more about this element on MDN: <input type="radio">
(opens in new tab).
HTML
<label class="form-label">My specialization is...</label>
<div class="form-check">
<input class="form-check-input" type="radio" value="backend" name="radio-group-1" id="example-radio-1">
<label class="form-check-label" for="example-radio-1">
Back-end engineering
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" value="frontend" name="radio-group-1" id="example-radio-2" checked>
<label class="form-check-label" for="example-radio-2">
Front-end engineering
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" value="fullstack" name="radio-group-1" id="example-radio-3" disabled>
<label class="form-check-label" for="example-radio-3">
Full-stack engineering (disabled)
</label>
</div>
Switch #
A switch has the markup of a custom checkbox but uses the additional .form-switch
class to render a toggle switch. Consider using role="switch"
to more accurately convey the nature of the control to assistive technologies that support this role. In older assistive technologies, it will simply be announced as a regular checkbox as a fallback. Switches also support the disabled
attribute.
HTML
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" value="" id="example-switch-1">
<label class="form-check-label" for="example-switch-1">
This is a switch
</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" value="" id="example-switch-2" checked>
<label class="form-check-label" for="example-switch-2">
This is another switch
</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" value="" id="example-switch-3" disabled>
<label class="form-check-label" for="example-switch-3">
Disabled switch
</label>
</div>
When to use over checkbox
It is often difficult to determine when to use a switch over a checkbox, as they are both fundamentally toggle components. One common view is that switches are for instantaneous actions, where users expect something to change as soon as one is toggled. This view, although debatable, can be backed by some actual research (opens in new tab).Inline #
By default, any number of checkboxes and radios that are immediate sibling will be vertically stacked and appropriately spaced with .form-check
. However, you can group checkboxes or radio buttons on the same horizontal row by adding the .form-check-inline
class to any .form-check
.
HTML
<!-- Inline checkboxes -->
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-5" checked>
<label class="form-check-label" for="example-checkbox-5">A</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-6">
<label class="form-check-label" for="example-checkbox-6">B</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-7" disabled>
<label class="form-check-label" for="example-checkbox-7">C (disabled)</label>
</div>
<!-- Inline radio buttons -->
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" value="d" name="radio-group-2" id="example-radio-4" checked>
<label class="form-check-label" for="example-radio-4">D</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" value="e" name="radio-group-2" id="example-radio-5">
<label class="form-check-label" for="example-radio-5">E</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" value="f" name="radio-group-2" id="example-radio-6" disabled>
<label class="form-check-label" for="example-radio-6">F (disabled)</label>
</div>
Reverse #
You can put your checkboxes, radio buttons, and switches on the opposite side with the .form-check-reverse
modifier class.
HTML
<!-- Reverse checkbox, radio button, and switch -->
<div class="form-check form-check-reverse">
<input class="form-check-input" type="checkbox" value="" id="example-checkbox-8">
<label class="form-check-label" for="example-checkbox-8">
Reverse checkbox
</label>
</div>
<div class="form-check form-check-reverse">
<input class="form-check-input" type="radio" value="" id="example-radio-7">
<label class="form-check-label" for="example-radio-7">
Reverse radio
</label>
</div>
<div class="form-check form-switch form-check-reverse">
<input class="form-check-input" type="checkbox" role="switch" value="" id="example-switch-4">
<label class="form-check-label" for="example-switch-4">
Reverse switch
</label>
</div>
Without labels #
Omit the wrapping .form-check
for checkboxes, radio buttons and switches that have no label text. Remember to still provide some form of accessible name for assistive technologies (for instance, using aria-label
).
HTML
<!-- Checkbox, radio button, and switch with no label -->
<div class="d-inline-block me-2">
<input class="form-check-input" type="checkbox" value="" aria-label="Checkbox with no label">
</div>
<div class="d-inline-block me-2">
<input class="form-check-input" type="radio" value="" aria-label="Radio button with no label">
</div>
<div class="d-inline-block form-switch">
<input class="form-check-input" type="checkbox" value="" aria-label="Switch with no label">
</div>
Toggle buttons #
You can also create button-like checkboxes and radio buttons by using .btn
styles rather than .form-check-label
on the <label>
elements. These toggle buttons can further be grouped in a button group if needed. Please note, outline buttons work best because of the look of the :checked
state being distinct from the base state.
HTML
<!-- Checkboxes as toggle buttons -->
<input type="checkbox" class="btn-check" id="example-checkbox-9" autocomplete="off">
<label class="btn btn-outline-primary" for="example-checkbox-9">Python</label>
<input type="checkbox" class="btn-check" id="example-checkbox-10" autocomplete="off">
<label class="btn btn-outline-primary" for="example-checkbox-10">JavaScript</label>
<input type="checkbox" class="btn-check" id="example-checkbox-11" autocomplete="off" disabled>
<label class="btn btn-outline-primary" for="example-checkbox-11">C++</label>
<!-- Radio buttons as toggle buttons -->
<input type="radio" name="radio-group-3" class="btn-check" id="example-radio-8" autocomplete="off">
<label class="btn btn-outline-primary" for="example-radio-8">Back-end</label>
<input type="radio" name="radio-group-3" class="btn-check" id="example-radio-9" autocomplete="off">
<label class="btn btn-outline-primary" for="example-radio-9">Front-end</label>
<input type="radio" name="radio-group-3" class="btn-check" id="example-radio-10" autocomplete="off" disabled>
<label class="btn btn-outline-primary" for="example-radio-10">Full-stack</label>
Accessibility
Visually, the checkbox toggle buttons are identical to the button plugin toggle buttons. However, they are conveyed differently by assistive technologies: the checkbox toggles will be announced by screen readers as checked
/ not checked
(since, despite their appearance, they are fundamentally still checkboxes), whereas the button plugin toggle buttons will be announced as button
/ button pressed
.
The choice between these two approaches will depend on the type of toggle you are creating, and whether or not the toggle will make sense to users when announced as a checkbox or as an actual button.
Help us grow
Our main goal is to make Halfmoon the go-to framework for building websites, dashboards and tools. If you believe in our mission, consider becoming a sponsor and help us grow.
You can email us directly if you have any queries. We are always happy to answer.
Subscribe for updates
We will notify you when the framework gets a substantial update. No spam ever.
Follow us on Twitter so that you can stay updated that way.