Bootstrap: BS v4: Add CSS Toggle Switch?

Created on 10 Feb 2015  路  13Comments  路  Source: twbs/bootstrap

Hey,

Would it be of any interest in version four to do a pull request for a CSS only toggle switch? It would have animations and slide like you'd expect

Example image:
screen shot 2015-02-10 at 2 11 00 pm

Essentially:

<label class="tgl">
  <input type="checkbox" checked/>
  <span class="tgl_body">
    <span class="tgl_switch"></span>
    <span class="tgl_track">
      <span class="tgl_bgd"></span>
      <span class="tgl_bgd tgl_bgd-negative"></span>
    </span>
  </span>
</label>

SCSS:

$toggle-height: 30px;
$toggle-width: 60px;
$switch-size: 30px;

$anim-slight-bounce: cubic-bezier(0.34,1.61,0.7,1);
$anim-speed-normal: 250ms;

$border-color: #dadde1;
$blue: #439fd8; // Guidebook blue

//   BASE
// -------------------------------------


.tgl {

  position: relative;
  display: inline-block;
  height: $toggle-height;
  cursor: pointer;

  > input {
    position: absolute;
    opacity: 0;
    z-index: -1; /* Put the input behind the label so it doesn't overlay text */
    visibility: hidden;
  }

  .tgl_body {
    width: $toggle-width;
    height: $toggle-height;
    background: white;
    border: 1px solid $border-color;
    display: inline-block;
    position: relative;
    border-radius: 50px;
  }

  .tgl_switch {
    width: $toggle-height;
    height: $toggle-height;
    display: inline-block;
    background-color: white;
    position: absolute;
    left: -1px;
    top: -1px;
    border-radius: 50%;
    border: 1px solid darken($border-color, 5%);
    @include box-shadow(0 2px 2px rgba(0,0,0,.13));
    @include transition(left $anim-slight-bounce $anim-speed-normal, transform $anim-slight-bounce $anim-speed-normal);
    z-index: 1;
  }

  .tgl_track {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
    border-radius: 50px;
  }

  .tgl_bgd {
    position: absolute;
    right: -10px; // 10 compensates for animation bounce
    top: 0;
    bottom: 0;
    width: $toggle-width - ($switch-size / 2) + 10; // 10 compensates for animation bounce
    @include transition(left $anim-slight-bounce $anim-speed-normal, right $anim-slight-bounce $anim-speed-normal);
    background: $blue url('http://petelada.com/images/toggle/tgl_check.png') center center no-repeat;
  }

  .tgl_bgd-negative {
    right: auto;
    left: -($toggle-width - ($switch-size / 2));
    background: white url('http://petelada.com/images/toggle/tgl_x.png') center center no-repeat;
  }

  &:hover {
    .tgl_switch {
      border-color: darken($border-color, 13%);
      @include transform(scale(1.06));
    }
  }

  &:active {
    .tgl_switch {
      @include transform(scale(.95));
    }
  }

  > :not(:checked) ~ .tgl_body {

    > .tgl_switch {
      left: $toggle-width - $switch-size;
    }

    .tgl_bgd {
      right: -($toggle-width - ($switch-size / 2));

      &.tgl_bgd-negative {
        right: auto;
        left: -10px;
      }
    }
  }
}
feature

Most helpful comment

All 13 comments

Also could be a simpler one like:

HTML

<div class="switch">
  <input id="cmn-toggle-4" class="cmn-toggle cmn-toggle-round-flat" type="checkbox">
  <label for="cmn-toggle-4"></label>
</div>

CSS:

.cmn-toggle {
  position: absolute;
  margin-left: -9999px;
  visibility: hidden;
}
.cmn-toggle + label {
  display: block;
  position: relative;
  cursor: pointer;
  outline: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
input.cmn-toggle-round-flat + label {
  padding: 2px;
  width: 120px;
  height: 60px;
  background-color: #dddddd;
  -webkit-border-radius: 60px;
  -moz-border-radius: 60px;
  -ms-border-radius: 60px;
  -o-border-radius: 60px;
  border-radius: 60px;
  -webkit-transition: background 0.4s;
  -moz-transition: background 0.4s;
  -o-transition: background 0.4s;
  transition: background 0.4s;
}
input.cmn-toggle-round-flat + label:before, input.cmn-toggle-round-flat + label:after {
  display: block;
  position: absolute;
  content: "";
}
input.cmn-toggle-round-flat + label:before {
  top: 2px;
  left: 2px;
  bottom: 2px;
  right: 2px;
  background-color: #fff;
  -webkit-border-radius: 60px;
  -moz-border-radius: 60px;
  -ms-border-radius: 60px;
  -o-border-radius: 60px;
  border-radius: 60px;
  -webkit-transition: background 0.4s;
  -moz-transition: background 0.4s;
  -o-transition: background 0.4s;
  transition: background 0.4s;
}
input.cmn-toggle-round-flat + label:after {
  top: 4px;
  left: 4px;
  bottom: 4px;
  width: 52px;
  background-color: #dddddd;
  -webkit-border-radius: 52px;
  -moz-border-radius: 52px;
  -ms-border-radius: 52px;
  -o-border-radius: 52px;
  border-radius: 52px;
  -webkit-transition: margin 0.4s, background 0.4s;
  -moz-transition: margin 0.4s, background 0.4s;
  -o-transition: margin 0.4s, background 0.4s;
  transition: margin 0.4s, background 0.4s;
}
input.cmn-toggle-round-flat:checked + label {
  background-color: #8ce196;
}
input.cmn-toggle-round-flat:checked + label:after {
  margin-left: 60px;
  background-color: #8ce196;
}

Which results in:
toggle-switch-2

X-Ref: #1935

Might want to propose this for https://github.com/mdo/wtf-forms/ first.

Proposed for wtf-forms as an issue: mdo/wtf-forms#47

Thanks for the suggestion @cvrebert. I'll be happy to implement in either place or both based on feedback.

I'm probably in favor of it, but this exact proposal (the examples) are a little glitchy it looks like.

Sounds good. Let me know what glitches you run into and I'll be happy to attempt to revise them. Starting points if nothing else :+1:

Although I the example looks very nice I would like to note, that some designs based on bootstrap are flat and without rounded corners. I hope this will be considered in the final design of such a toggle/switch. Thanks

Punting on this鈥攚e're not leaving issues open for v4 until we do the alpha.

Do you plan to add this to Bootstrap 4?

no current plans for this, no

the more I've looked into this @paglias the more difficult it seems to ensure that it really works consistently across browsers while maintaining proper accessibility. I could just be missing something though of course

I understand, thanks anyway :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tobi-or-not-tobi picture tobi-or-not-tobi  路  75Comments

rpkilby picture rpkilby  路  65Comments

sts-ryan-holton picture sts-ryan-holton  路  37Comments

andrade1379 picture andrade1379  路  41Comments

XhmikosR picture XhmikosR  路  43Comments