1

How can I (CSS-only) style an input with type="checkbox", and keep the existing label declared for that input element?

<p id="lorem-ipsum">
    <label for="dolor-sit-amet">Dolor sit amet</label>
    <input type="checkbox" id="dolor-sit-amet" name="dolor" />
</p>

I want to style the checkbox element so that it has a "flip switch" appearance and behaviour.

Keep the existing label

There are numerous articles (an example from 2012) that describe this kind of complete change to the appearance of a checkbox, but I haven't found one that lets the label (as already used in the above document) remain untouched.

For this reason, many of the answers in this similar StackOverflow question do not apply here.

In other words: I want to keep the label element as already written, and I want to have the checkbox styled like a flip switch with "on" and "off" inside it.

How can I do that without changing or styling the existing label element, and instead styling the input element?

bignose
  • 30,281
  • 14
  • 77
  • 110
  • 1
    "How can I do that without changing the existing label element, by styling just the input element?" - by just styling the `input`, you're still out of luck. The answer by [Aje](https://stackoverflow.com/a/52713990/4665) is a great compromise by using `::before` and `::after` pseudo elements. – Jon P Oct 09 '18 at 05:55
  • @JonP, thanks for helping me clarify. I am updating the question to be clear it's specifically the `label` I want to avoid changing. – bignose Oct 09 '18 at 12:01

2 Answers2

2

if you can change the sequence in label and input, here is an idea. you can change the colors and add animation as per your requirement.

label{
position:relative;
display:block;
width:200px;
}
label:before{
  content:'off';
  width:50px;
  height:20px;
  background:#eee;
  border-radius:50px;
  position:absolute;
  right:0
  
}
label:after{
  content:'';
  width:18px;
  height:18px;
  background:#333;
  border-radius:50px;
  position:absolute;
  right:1px;
  top:1px;
  
}
input:checked + label:before{
  content:'on';
  text-indent: 25px;
  
  
}
input:checked + label:after{
  right:29px;
  top:1px;
  
}
<p id="lorem-ipsum">
    <input type="checkbox" id="dolor-sit-amet" name="dolor" />
    <label for="dolor-sit-amet">Dolor sit amet</label>
    
</p>
AG_
  • 2,589
  • 3
  • 20
  • 32
  • This is intriguing, but doesn't hit the mark. I do still want to have the switch appear in the same position (before the label). Also, tying the extra content so closely to the label element forecloses other styling of the label. I've used this to build [my answer](https://stackoverflow.com/a/52720932/70157), though, so thank you! – bignose Oct 09 '18 at 12:24
0

The :before and :after selectors can create some of the content. By adding another element (for example, a span) that can be styled to appear as the “slider” of the switch.

Then, the containing element – which can be the label itself! – can also have :before and :after selectors used to style the “socket” in which the slider moves.

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

label.switch.socket {
    position: relative;
    width: auto;
    text-indent: 6.0ex;
}
span.switch.slider {
    display: inline-block;
}
label.switch.socket span.switch.slider:before {
    content: "off";
    text-indent: 2.3ex;
    width: 5.5ex;
    height: 2.2ex;
    color: White;
    background: DimGray;
    border-radius: 5.5ex;
    position: absolute;
    left: 0;
}
label.switch span.switch.slider:after {
    content: "";
    width: 2.0ex;
    height: 2.0ex;
    background: Gainsboro;
    border-radius: 5.5ex;
    position: absolute;
    left: 0.1ex;
    top: 0.1ex;
    transition: 0.2s;
}
label.switch.socket input[type=checkbox]:checked + span.slider:before {
    content: "on";
    text-indent: 0.5ex;
    color: Black;
    background: DarkGray;
}
label.switch.socket input[type=checkbox]:checked + span.slider:after {
    left: 3.4ex;
}
<p>
    <label class="switch socket">
        <input type="checkbox" class="switch" name="lorem" />
        <span class="switch slider" />
        Lorem ipsum
    </label>

    <label class="switch socket">
        <input type="checkbox" class="switch" name="dolor" checked />
        <span class="switch slider round" />
        Dolor sit amet
    </label>
</p>

(Thanks to @gosi123 and @aje for suggestions that came close enough to help me formulate this answer.)

bignose
  • 30,281
  • 14
  • 77
  • 110