Checkbox Madness

Wednesday 30th May, 2018 —

Html Checkboxes ?

Like many native html elements, out of the box checkboxes suffer from a really poor design. This makes the checkbox customization task almost mandatory in every project. in return, what is truely great is that talented designers and developers came up with awesome and crazy ideas to use checkboxes in a variety of situations and setups.

Building a checkbox based component

What is interesting with the checkbox is that we can only keep the behaviour and totally change the purpose of the UI. The main thing to keep in mind is that checkboxes provide 2 states :

  • Unchecked state: the checkbox default state
  • Checked state: the checkbox active state

This allows us to make use of it to build any kind of togglable component, with an active and a default state. It really doesn't have to look like a checkbox, design speaking, but just needs to have the same behaviour.

What we'll be building

In this article we will be building a custom checkbox that looks like a switch component. We will use this switch to toggle our bad mood !

Getting started

Tutorial Code

You can find all the code used for this tutorial in the following Pen.

See the Pen Mood Toggle by Driss Chelouati (@cssninjaStudio) on CodePen.

Html Markup

Let's begin with the html markup we are going to need for our custom switch / checkbox. Also note that we will use the Material Icons library to display a happy and a sad smiley. Note that we won't be needing any javascript to make everything work

<label class="mood-toggle">  <input type="checkbox" />  <span class="toggler">    <span class="happy">      <i class="material-icons">mood</i>    </span>    <span class="sad">      <i class="material-icons">sentiment_very_dissatisfied</i>    </span>  </span></label>

To create our custom checkbox component, we first need to wrap it inside a <label></label> html element. We are giving this label a class named .mood-toggle that we will use to inject our styles and make them component scoped. Our label will act as a container for the two sub elements that will make this custom checkbox work:

  • A checkbox input element from witch we will only keep the checkbox behaviour.
  • A span element that will receive all the custom styles that we need to make our checkbox / switch stand out. It serves as a container for the 2 icon boxes that we will use as knobs for our switch.

Adding styles

First of all, we need to declare 2 color variables that we will use to represent each state of our switch. You can basically choose any colors. In our case we chose an orange tint for the sad state and a light blue tint for the happy state.

$primary: #ff5722;$accent: #448aff;

Let's then start by styling our .mood-toggle element, wich serves as a container for our switch. The width and the margin properties remain optional. We defined them in this example in order to have more control on the switch positioning in the layout. We make it unselectable as it should not behave as a text span or any other text element. What is important here is the position property. We set it to relative so we can easily use absolute position for its children elements.

.mood-toggle {  margin: 0 auto;  width: 86px;  display: block;  position: relative;  margin-bottom: 12px;  cursor: pointer;  font-size: 22px;  -webkit-user-select: none;  -moz-user-select: none;  -ms-user-select: none;  user-select: none;}

Let's now deal with the checkbox native input element. We need to keep it's functionnality but we also need to hide it at the same time. To achieve that, we are simply using absolute position and increasing it's opacity to 100%, making it totally transparent, and therefore invisible. At this stage, if you try clicking on the .mood-toggle element, you'll notice that the checkbox input will still continue to be toggled after a click on it.

.mood-toggle {  input {    position: absolute;    opacity: 0;    cursor: pointer;  }}

It is now the time to style the inner switch box, that contains the 2 switch knobs. We will also relatively position it because we will need absolute position for the icon knobs. What is important here is that we define an arbitrary height and width, for our design to match. This has a direct influence on the knobs sizes. We are also giving the element a default orange border that we will change when the switch is toggled.

.mood-toggle {  .toggler {    position: relative;    display: block;    height: 44px;    width: 80px;    border: 2px solid $primary;    border-radius: 100px;    transition: all 0.3s;  }}

Let's also add the styles for the inner sibling elements, that will serve as knobs for our switch. We are first setting up basic styles that the 2 knobs will share. First, we are using flexbox to ensure that the icons are properly centered inside each knob. the transform property is set to 0 for both translate and rotate, wich gives us the initial state for our knobs. What is extremely important here is the absolute position. We are giving the same position value to each knob because we want them to stack. This way we ensure that the two knobs will move the same way. However, we still need to differenciate each one of the knobs. We are supposed to see only one of them at a time. This is why we are giving an opacity of 1 to .sad(displayed by default, when the checkbox is unchecked) and 0 to the .happy. Each one is also given its own color.

.mood-toggle {  .toggler {    .happy,    .sad {      position: absolute;      top: 2px;      left: 2px;      height: 36px;      width: 36px;      border-radius: 50%;      background: black;      display: flex;      justify-content: center;      align-items: center;      transform: translateX(0) rotate(0);      transition: all 0.3s ease;      i {        color: white;        font-size: 22px;      }    }    .sad {      background: $primary;      border-color: $primary;      opacity: 1;      z-index: 1;    }    .happy {      background: $accent;      border-color: $accent;      opacity: 0;      z-index: 0;    }  }}

Finally, we just need to update the styles when the checkbox is in the checked state. getting the right selector in this setup can be a little tricky because the .toggler element is a sibling of the input. Hopefully, CSS provides a selector for that : ~ . So what happens here? We simply tell the browser to translate the 2 knobs to the right when the input's checked attribute value is true. Then, we simply let the magic take place with a few additional properties: we simply fade out the .sad knob and show the .happy one while translating and rotating both to the right, with the help transitions.

.mood-toggle {  .toggler {    input {      &:checked ~ .toggler {        border-color: $accent;        .happy,        .sad {          transform: translateX(100%) rotate(360deg);        }        .happy {          opacity: 1;        }        .sad {          opacity: 0;        }      }    }  }}

Congratulations! Our checkbox based custom switch now works, without a single line of Javascript.


In this post, we saw how to create a simple checkbox based custom switch using transitions. If you want to share your thoughts or ask a question, give it a shot in the comments section. I hope you enjoyed this little session as much as i did writing it and to see you again soon on Css Ninja.

Back to Blog

Continue reading