<!--

Usage:

  <span class="switch">
    <input type="checkbox" class="switch" id="switch-id">
    <label for="switch-id">Small switch</label>
  </span>
  
Notes:

 - The label must directly proceed input
 - The input must have an id
 - The label must have for="<id>"

-->

<!-- Small switch -->
<div class="form-group">  
  <span class="switch switch-sm">
    <input type="checkbox" class="switch" id="switch-sm">
    <label for="switch-sm">Small switch</label>
  </span>
</div>

<!-- Normal switch -->
<div class="form-group">
  <span class="switch">
    <input type="checkbox" class="switch" id="switch-normal">
    <label for="switch-normal">Normal switch</label>
  </span>
</div>

<!-- Large switch -->
<div class="form-group">
  <span class="switch switch-lg">
    <input type="checkbox" class="switch" id="switch-lg">
    <label for="switch-lg">Large switch</label>
  </span>
</div>
//
// Switches for Bootstrap 4.
//
// - Fully customizable with Sass variables
// - No JavaScript required
// - Fully accessible
//

//
// IMPORTANT: These Sass variables are defined in Bootstrap's variables.scss. You should import that file first, then remove these.
//
$font-size-base: 1rem;
$font-size-lg: ($font-size-base * 1.25);
$font-size-sm: ($font-size-base * .875);
$input-height: 2.375rem;
$input-height-sm: 1.9375rem;
$input-height-lg: 3rem;
$input-btn-focus-width: .2rem;
$custom-control-indicator-bg: #dee2e6;
$custom-control-indicator-disabled-bg: #e9ecef;
$custom-control-description-disabled-color: #868e96;
$white: white;
$theme-colors: (
  'primary': #08d
);

//
// These variables can be used to customize the switch component.
//
$switch-height: calc(#{$input-height} * .8) !default;
$switch-height-sm: calc(#{$input-height-sm} * .8) !default;
$switch-height-lg: calc(#{$input-height-lg} * .8) !default;
$switch-border-radius: $switch-height !default;
$switch-bg: $custom-control-indicator-bg !default;
$switch-checked-bg: map-get($theme-colors, 'primary') !default;
$switch-disabled-bg: $custom-control-indicator-disabled-bg !default;
$switch-disabled-color: $custom-control-description-disabled-color !default;
$switch-thumb-bg: $white !default;
$switch-thumb-border-radius: 50% !default;
$switch-thumb-padding: 2px !default;
$switch-focus-box-shadow: 0 0 0 $input-btn-focus-width rgba(map-get($theme-colors, 'primary'), .25);
$switch-transition: .2s all !default;

.switch {
  font-size: $font-size-base;
  position: relative;

  input {
    position: absolute;
    height: 1px;
    width: 1px;
    background: none;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    overflow: hidden;
    padding: 0;

    + label {
      position: relative;
      min-width: calc(#{$switch-height} * 2);
      border-radius: $switch-border-radius;
      height: $switch-height;
      line-height: $switch-height;
      display: inline-block;
      cursor: pointer;
      outline: none;
      user-select: none;
      vertical-align: middle;
      text-indent: calc(calc(#{$switch-height} * 2) + .5rem);
    }

    + label::before,
    + label::after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: calc(#{$switch-height} * 2);
      bottom: 0;
      display: block;
    }

    + label::before {
      right: 0;
      background-color: $switch-bg;
      border-radius: $switch-border-radius;
      transition: $switch-transition;
    }

    + label::after {
      top: $switch-thumb-padding;
      left: $switch-thumb-padding;
      width: calc(#{$switch-height} - calc(#{$switch-thumb-padding} * 2));
      height: calc(#{$switch-height} - calc(#{$switch-thumb-padding} * 2));
      border-radius: $switch-thumb-border-radius;
      background-color: $switch-thumb-bg;
      transition: $switch-transition;
    }

    &:checked + label::before {
      background-color: $switch-checked-bg;
    }

    &:checked + label::after {
      margin-left: $switch-height;
    }

    &:focus + label::before {
      outline: none;
      box-shadow: $switch-focus-box-shadow;
    }

    &:disabled + label {
      color: $switch-disabled-color;
      cursor: not-allowed;
    }

    &:disabled + label::before {
      background-color: $switch-disabled-bg;
    }
  }

  // Small variation
  &.switch-sm {
    font-size: $font-size-sm;

    input {
      + label {
        min-width: calc(#{$switch-height-sm} * 2);
        height: $switch-height-sm;
        line-height: $switch-height-sm;
        text-indent: calc(calc(#{$switch-height-sm} * 2) + .5rem);
      }

      + label::before {
        width: calc(#{$switch-height-sm} * 2);
      }

      + label::after {
        width: calc(#{$switch-height-sm} - calc(#{$switch-thumb-padding} * 2));
        height: calc(#{$switch-height-sm} - calc(#{$switch-thumb-padding} * 2));
      }

      &:checked + label::after {
        margin-left: $switch-height-sm;
      }
    }
  }

  // Large variation
  &.switch-lg {
    font-size: $font-size-lg;

    input {
      + label {
        min-width: calc(#{$switch-height-lg} * 2);
        height: $switch-height-lg;
        line-height: $switch-height-lg;
        text-indent: calc(calc(#{$switch-height-lg} * 2) + .5rem);
      }

      + label::before {
        width: calc(#{$switch-height-lg} * 2);
      }

      + label::after {
        width: calc(#{$switch-height-lg} - calc(#{$switch-thumb-padding} * 2));
        height: calc(#{$switch-height-lg} - calc(#{$switch-thumb-padding} * 2));
      }

      &:checked + label::after {
        margin-left: $switch-height-lg;
      }
    }
  }

  + .switch {
    margin-left: 1rem;
  }
}

//
// Demo only
//
body {
  padding: 1rem;
}

.dropdown-menu {
  margin-top: .75rem;
}
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css

External JavaScript

  1. https://code.jquery.com/jquery-3.2.1.slim.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/js/bootstrap.min.js