Search code examples
htmlcsstoggle

How can I style a toggle to include a tick and cross?


I have a standard toggle switch, which I would like to style to resemble below using CSS only.

enter image description here

I have seen the following example, which achieves the effect:

HTML

<input type="checkbox" id="toggle"/>
<div>
  <label for="toggle"></label>
</div>

CSS

*,
*::before,
*::after {
  transition: 400ms all ease-in-out 50ms;
  box-sizing: border-box;
  backface-visibility: hidden;
}

input[type="checkbox"] {
  display: none;
}

/* Toggle State is :CHECKED */

input[type="checkbox"]:checked ~ div {
  background: rgba(0, 122, 122, 1); /* Teal bg */

}

input[type="checkbox"]:checked ~ div label {
  left: 18px;
}

/* Shared */

div,
label {
  border-radius: 9999px;
}

/* Toggle State is 'un':checked */

div {
  height: 26px;
  width: 42px;
  background: rgba(224, 224, 224, 1); /* grey bg */
  position: relative;
  top: calc(50vh - 50px);
  left: calc(50vw - 100px);
  
}

label {
  height: 22px;
  width: 22px;
  background: rgba(255, 255, 255, 1); /* white knob */
  position: absolute;
  top: 2px;
  left: 2px;
  cursor: pointer;
 
}

label::before {
  content: '';
  height: 15.5px;
  width: 1px; /* stroke */
  position: absolute;
  top: calc(50% - 8px);
  left: calc(50% - 1px);
  transform: rotate(45deg);
}

label::after {
  content: '';
  height: 1px; /* stroke */
  width: 15.5px;
  position: absolute;
  top: calc(50% - 0.5px);
  left: calc(50% - 8px);
  transform: rotate(45deg);
}

label::before,
label::after{
  background: rgba(97, 97, 97, 1);
  border-radius: 2px;
}

/* pesduo class on toggle */

input[type="checkbox"]:checked ~ div label::before{
  height: 12.5px;
  top: calc(55% - 6.5px);
  left: calc(60% - 1px);
  background: rgba(37,127,57,1);
}

input[type="checkbox"]:checked ~ div label::after{
  width: 6px;
  top: calc(95% - 7.5px);
  left: calc(22.5% - 1.5px);
  background: rgba(37,127,57,1);
}

https://codepen.io/nuxpr/pen/YzabjeB

However this will not work for me since my HTML is different and cannot be changed. Here is my HTML.

HTML

<div class="my-tgl">
  <input type="checkbox" id="my-group-id-Targt"> 
  <label class="my-switch" for="my-group-id-Targt">
    <span class="my-switch-nob" role="switch"></span>
  </label> 
</div>

Solution

  • There we go, just replacing div with label and label with span. (Also making the label and the span display:block). That did the trick. You can prefix all with your div.class if you want to namespace this.

    *,
    *::before,
    *::after {
      transition: 400ms all ease-in-out 50ms;
      box-sizing: border-box;
      backface-visibility: hidden;
    }
    
    input[type="checkbox"] {
      display: none;
    }
    
    
    /* Toggle State is :CHECKED */
    
    input[type="checkbox"]:checked ~ label {
      background: rgba(0, 122, 122, 1);
      /* Teal bg */
      box-shadow: 0 2px 1px -1px rgba(0, 0, 0, .2) 0 1px 1px 0 rgba(0, 0, 0, .14) 0 1px 3px 0 
    }
    
    input[type="checkbox"]:checked ~ label span {
      left: 18px;
      transform: rotate(360deg);
    }
    
    
    /* Shared */
    
    label,
    span {
      border-radius: 9999px;
    }
    
    
    /* Toggle State is 'un':checked */
    
    label {
      height: 26px;
      width: 42px;
      background: rgba(224, 224, 224, 1);
      /* grey bg */
      position: relative;
      top: calc(50vh - 50px);
      left: calc(50vw - 100px);
      display:block;
    
    }
    
    span {
      height: 22px;
      width: 22px;
      background: rgba(255, 255, 255, 1);
      /* white knob */
      position: absolute;
      top: 2px;
      left: 2px;
      cursor: pointer;
      box-shadow: 0 2px 1px -1px rgba(0, 0, 0, .2) 0 1px 1px 0 rgba(0, 0, 0, .14) 0 1px 3px 0 rgba(0, 0, 0, .12);
    }
    
    span::before {
      content: '';
      height: 15.5px;
      width: 1px;
      /* stroke */
      position: absolute;
      top: calc(50% - 8px);
      left: calc(50% - 1px);
      transform: rotate(45deg);
    }
    
    span::after {
      content: '';
      height: 1px;
      /* stroke */
      width: 15.5px;
      position: absolute;
      top: calc(50% - 0.5px);
      left: calc(50% - 8px);
      transform: rotate(45deg);
    }
    
    span::before,
    span::after {
      background: rgba(97, 97, 97, 1);
      border-radius: 2px;
    }
    
    
    /* pesduo class on toggle */
    
    input[type="checkbox"]:checked ~ label span::before {
      height: 12.5px;
      top: calc(55% - 6.5px);
      left: calc(60% - 1px);
      background: rgba(37, 127, 57, 1);
    }
    
    input[type="checkbox"]:checked ~ label span::after {
      width: 6px;
      top: calc(95% - 7.5px);
      left: calc(22.5% - 1.5px);
      background: rgba(37, 127, 57, 1);
    }
    <div class="my-tgl">
      <input type="checkbox" id="my-group-id-Targt"> 
      <label class="my-switch" for="my-group-id-Targt">
        <span class="my-switch-nob" role="switch"></span>
      </label> 
    </div>