As a designer you will sooner or later get to the point where you have to design custom input elements, even though it's fairly easy to make text-inputs look pretty it can be hard at times to code a good looking checkbox with css alone. Today I'm going to show you my way of making custom css checkboxes.

Admittedly, it's not the most cross-browser compatible way of styling checkboxes. One could even see it as a little css hack. For Chrome and Firefox users it will be displayed just fine but IE as well as Edge do not support this, so if you do need a more compatible solution whatsoever you could try this method from w3schools.

But now let's begin. Here's how it should look like:

Normal checkbox
Checkbox with other icon
Disabled checkbox
Disabled checkbox (checked)



How it works:

                        
                            <input class="checkbox" type="checkbox" data-icon="check">
                        
                        
                    
First we create a normal checkbox with a chosen class and a data-attribute. (In this case "data-icon") I explain why we use the attribute later on.

                        .checkbox{
                              -webkit-appearance: none;
                              -moz-appearance: none;
                              appearance: none;
                
                              background: #ccc;
                              color: #0057ff;
                              margin: 5px;
                              width: 20px;
                              height: 20px;
                              border-radius: 2px;
                              cursor: pointer;
                              position: relative;
                              vertical-align: middle;
                            }
                            .checkbox::before{
                              content: attr(data-icon);
                              width: 20px;
                              height: 20px;
                              line-height: 20px;
                              text-align: center;
                              position: absolute;
                              top: 0;
                              left: 0;
                              color: inherit;
                              font-size: 0;
                              font-family: 'Material Icons';
                              transition: 80ms;
                            }
                            .checkbox:checked::before{
                              font-size: 18px;
                            }
                            .checkbox:disabled{
                              color: #aaa;
                              background: #ddd;
                              cursor: default;
                            }
                        
                    
Next up we style the checkbox by first disabling the default browser styling. This is done with appearance: none. Then we are free to design the checkbox to our desire. When we test it now we'll see two things:
  • Our own styling is applied
  • The checkmark has disappeared
So now we have to create the checkmark ourselfs. And there the CSS pseudo elements ::before and ::after come in handy. (This is the part where Edge stops playing nice and just goes back to it's standard checkbox design while completely ignoring our styling/appearance properties). Pseudo elements allow us to create two more elements inside the Original DOM element without writing more HTML. They also need to have the content property to be set. And while we could just put a background image in the pseudo-element I decided to use a neat little feature which comes with the content expression. By setting content to attr() we're now able to take any HTML attribute and put it in place of the inner content.

For example: content: attr(class) would give us "checkbox" as text.

With that alone we can use special characters like ✓ or ✗. But we can top this of by using any web-icon-font. In this example I use Googles Material Icons but fonts like Font Awesome should work too. When we now set content to attr(data-icon) and put a valid icon name in the data-attribute (For M.I. it would be "check" or "apps") it displays the icon instead of the text.

To finish this we have to disable the checkmark by default and only show it when the checkbox is checked. You can use font-size: 0px to hide it and set the font-size to something bigger when it's :checked. (Allows you to let it transition)

How you design your checkbox is up to you but with these little tricks it should be easy and fun to do so.

😉

Go back