Checkbox and radio

Consistent cross-browser and cross-device checkboxes, radio buttons, and switches.

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>

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>
Up next
Range

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.