iOS7 Style Pure CSS Toggle

iOS7 Style Pure CSS Toggle

Posted on Sep 19, 2013

I see these switch-style toggles everywhere lately - maybe it's the influence that iOS has on the design world. The source of the trend aside, I see a lot of folks using javascript to create them. This seems a little silly to me, since the HTML and CSS to accomplish them already exists (and is well supported to boot!). Have I piqued your curiosity? Read on, intrepid coder.

As with a lot of my smaller tutorials, we're going to be keeping the code for this one as simple as humanly possible. We're using one html input (a checkbox) along with its label. To style the element, we're using one CSS class and a couple of pseudo-elements along with the :checked pseudo-class.

An important thing to note for this switch is that the animation (using the CSS3 transition property) is only supported on some browsers, as we're applying it to the pseudo-elements. Chris Coyier over at CSS-Tricks.com has a handy table (if a little bit dated at this point) showing the support for this.

Enough jabbering - on to the code.

First, we establish the building block for the switch: a simple checkbox.

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

Got that? Ok—let's make it pretty. First, we're going to get rid of that pesky default checkbox. Each browser styles it a little differently, and we want complete control of the look, so we're going to take away it's width and height and then make it totally transparent. This means that the checkbox is still functional (that part is important), but not visible, and not affecting other elements' placement.

input#toggle {
max-height: 0;
max-width: 0;
opacity: 0;
}

Good stuff. Now that we've got that taken care of, we can style the actual switch. We're using the checkbox's label for this. There are three parts to the switch:

  • The container (this uses the actual label)
  • The switch itself (this uses the :after pseudo-element)
  • The switch's background (this uses the :before pseudo-element)
input#toggle + label {
display: block;
position: relative;
box-shadow: inset 0 0 0px 1px #d5d5d5;
text-indent: -5000px;
height: 30px;
width: 50px;
border-radius: 15px;
}

input#toggle + label:before {
content: "";
position: absolute;
display: block;
height: 30px;
width: 30px;
top: 0;
left: 0;
border-radius: 15px;
background: rgba(19,191,17,0);
-moz-transition: .25s ease-in-out;
-webkit-transition: .25s ease-in-out;
transition: .25s ease-in-out;
}

input#toggle + label:after {
content: "";
position: absolute;
display: block;
height: 30px;
width: 30px;
top: 0;
left: 0px;
border-radius: 15px;
background: white;
box-shadow: inset 0 0 0 1px rgba(0,0,0,.2), 0 2px 4px rgba(0,0,0,.2);
-moz-transition: .25s ease-in-out;
-webkit-transition: .25s ease-in-out;
transition: .25s ease-in-out;
}

A few things about that chunk of code. First off, you may notice that I'm using an inset box-shadow instead of border for my outlines. This allows me to have borders that overlap each other, so that the switch is flush to each side of its container. I'm also using CSS3 transitions to animate the switch, and as mentioned above, this isn't as supported as it should be for pseudo-elements (although support is getting better). Lastly, I'm using border-radius to round out the corners.

Now let's style the active state:

input#toggle:checked + label:before {
width: 50px;
background: rgba(19,191,17,1);
}

input#toggle:checked + label:after {
left: 20px;
box-shadow: inset 0 0 0 1px rgba(19,191,17,1), 0 2px 4px rgba(0,0,0,.2);
}

This moves the switch 20 pixels to the right and widens the background so that it is visible behind the switch, while also changing the inset box-shadow to the same color as the background. And presto—a beautiful and functional switch for your next project. Feel free to check out the demo!

←  Responsive CSS3 Lightbox with No Javascript My Take on iOS7  →

There are 9 comments. Add Yours.

*

*

Notify me of new replies

Allowed tags: <b><i><br>

*

Comments

  1. Mazhar Ahmed

    Mazhar Ahmed

    Oct 12, 2013 at 11:36 AM
    Awesome, I just made my own iCheckBox today and now found yours. It's great.

    Reply

    *

    *

    Notify me of new replies

    Allowed tags: <b><i><br>

    *

  2. Ramon Y

    Ramon Y

    Dec 13, 2013 at 02:53 PM
    This was a good start and really helped me out. But you might find this to be more accurate to what Apple's toggle looks like, and I removed the need for the label. Enjoy.

    http://www.cyberantics.net/toggle.html

    Reply

    *

    *

    Notify me of new replies

    Allowed tags: <b><i><br>

    *

    1. Jesse

      Jesse

      Dec 17, 2013 at 10:14 AM
      Thanks Ramon - that is quite nice! The one thing you may want to be wary of is using any input like this:

      < input >< / input >

      That closing tag is not the correct usage of the input html element. Technically, it allows you to eliminate the label but isn't the proper way to write input. If you are writing XHTML (your demo isn't - it's just using html5), then your closing tag would be "< input / >".

      For more info on this, check here: http://www.w3schools.com/tags/tag_input.asp

      Additionally, you may want to use CSS to remove the outline around the checkbox on :focus and :active. Just a thought!

      Thanks again for your feedback and the interesting tweak. Keep up the awesome work.

  3. Ben

    Ben

    Jan 17, 2014 at 02:43 AM
    Very clean. I dropped two on a page. They don't play nice together. How would it work with two on the same page?

    Reply

    *

    *

    Notify me of new replies

    Allowed tags: <b><i><br>

    *

    1. Jesse

      Jesse

      Jan 23, 2014 at 01:13 PM
      It's important to remember to include unique values and ids for each checkbox - that is not included in the demo. Also, each label should reference its unique checkbox id. For instance, here is a set of two checkboxes that belong to the same group, but operate independently:

      <input type="checkbox" name="checkbox-group" id="red-id" value="red"/>
      <label for="red-id">Red</label>
      <input type="checkbox" name="checkbox-group" id="blue-id" value="blue"/>
      <label for="blue-id">Blue</label>


      Hope this helps!

    2. Vytas

      Vytas

      Mar 29, 2014 at 08:45 AM
      Looks great, however I can't make working two together... Can you present demo of two working together?

      Thanks

    3. Jesse

      Jesse

      Mar 29, 2014 at 08:53 AM
      I'll see what I can do!

  4. Andreas Uppström

    Andreas Uppström

    Mar 19, 2014 at 06:33 AM
    Very nice, works "out of the box"!
    Thanks!

    Reply

    *

    *

    Notify me of new replies

    Allowed tags: <b><i><br>

    *

    1. Jesse

      Jesse

      Mar 19, 2014 at 07:46 AM
      Thanks, Andreas! There's a lot of these floating around, but I'm most happy with my solution (not necessarily better, but more to my own preference).