We're live-coding on Twitch! Join us!
Create a Google Polymer Checkbox Using CSS3

Create a Google Polymer Checkbox Using CSS3

Code Demo

After watching Google's I/O 2014 keynote yesterday, it became clear they were moving to a more unified design and UI language. This came in the form of what they called Material Design and extensively used Polymer, their new open-sourced framework.

I'll be sure to dive into Polymer further coming soon, but what struck me at first was the fun UI interactions that it brought to the table. This could be seen when viewing their demos:

Polymer Demos

While all these are great, I thought I'd take one of my favorite demos and try to recreate it in just CSS since Polymer uses Web Components. Here is a demo of what we'll be making today.

See the Pen Pure CSS3 Google Polymer Checkboxes by Chris Sevilleja (@sevilayha) on CodePen.

The Polymer Checkboxes

Here is the Polymer demo for checkboxes. What we'll be doing today is going through and creating this in CSS. We'll go over some fun techniques like pseudo elements and how to use CSS transitions and animations.

This technique of styling checkboxes and their corresponding labels is similar to our other checkboxes we've created in the past: Pure CSS3 Star Wars Lightsaber Checkboxes

Let's get started.

Setting Up Our HTML

For this demo, we will need a checkbox and a label. We will also add three span tags within our label to use for styling the moving parts that we need to make this look good.

better.dev Get Started w/ JavaScript for free!

<main class="container">

<div id="check-awesome" class="form-group">    
    <input type="checkbox" id="check-me">  

    <label for="check-me">
        <span class="circle"></span>
        <span class="check"></span>
        <span class="box"></span>

    <p>Notify me about how great I am every hour.</p>


Note that we are developing within CodePen and are using Bootstrap

That is all we will need for our HTML. Everything from here on out will be CSS and then we'll add in a little bit of JavaScript to handle rerunning an animation.

Basic Stylings

To get the animation for our checkbox, we will use the three span tags. Here is what the process will look like:

  • Style the three span tags for the various components (empty box, check, and the circle)
  • Use transitions for showing/hiding the box and the check
  • Use an animation for the circle and a little JavaScript to rerun the CSS animation

The Hiding Input Technique

To style up our checkbox, we will be hiding our input box and using the pseudo selector (input:checked ~ label) to style the checked and unchecked input. For more information on this way of styling checkboxes, read this, this, and this.

Styling the Checkbox

These are what we are using the 3 span tags for. Each one has its own purpose and having all three of these move and act together will create a great final effect.


Here is the CSS for all three parts. We'll add in some basic stylings for our entire experiment and then go through each one with comments.

/* basic css styling ------------------------------- */
input[type=checkbox]   { display:none; }        /* hide the checkbox */
label, p               { padding-left:50px; } 
#check-awesome         { position:relative; }

/* checkbox css ------------------------------------ */

/* show a cursor when we hover */
label                  { cursor:pointer; }

/* style all of our span tags with position absolute and over to the left */
label span             { display:block; position:absolute; left:0; 

/* style our circle and position it */
label .circle          {

/* style our box */
label .box     {
  border:2px solid #000;

/* style the check. give it a border on the bottom and right only and then rotate */
label .check         {
  top: -7px;
  left: 6px;
  width: 12px;
  height: 24px;
  border:2px solid #0f9d58;  
  border-top: none;
  border-left: none;

For simplicities sake, we have only used the default CSS3 properties without the prefixes (-webkit-, -moz-). The final code has all the prefixes.

Now you can start to see the basic styling of our checkbox happen. We have our checkbox and it's looking good, but if we click it, nothing happens. Don't worry though, even though nothing visually happens, we are still actually checking and unchecking our checkbox.

How does it know we are checking the checkbox? By default, in HTML5, if you have the for="" attribute on a label, it will automatically correspond to the matching id="". In this case, our label is label for="check-me" and our input is input type="checkbox" id="check-me".

With that good stuff out of the way. Let's handle clicking our checkbox and seeing transitions and animations happen.

Animating Our Checkbox


We'll be using transitions for the box and the check. Since we already defined the transition for our span tags by specifying transition-duration:0.3s, we can go ahead and style what they will look like when our checkbox is checked.

CSS transitions will automatically transition from how they are currently styled to how we want them to be styled. Our box will rotate and disappear, while our checkbox rotates and appears.

We'll style these using the pseudo CSS we talked about earlier.

// previous code up here ...

/* rotate and then hide our box */
input[type=checkbox]:checked ~ label .box {  
  transform:scale(0) rotate(-180deg);

/* rotate and show our check */
input[type=checkbox]:checked ~ label .check {
  transform:scale(1) rotate(45deg);

Now when we click our checkbox, we can see the animation take place for our box and our checkbox.


The next thing we need to handle is the @keyframe animation for our circle. Now you might be asking why we are using an animation for this instead of a transition? In a transition, there are only two states. Off and on.

For our circle, we want it to start small and transparent and then grow and become darker. Since there are multiple states we want to account for, an animation is the way to go.

Here is the code for that.

label .circle {
  animation:growCircle 0.3s ease;

@keyframes growCircle {
  0%, 100%   { transform:scale(0); }
  70%        { background:#DDD; transform:scale(1.25); }

When it starts, it will be scaled to 0. Then at 70%, it grows and gets darker. Then we have it shrink quickly back down to nothing.

Now go ahead and click on your checkbox and you'll be able to see the circle grow and shrink while the box and check hide and show!

JavaScript to ReRun Animations

With CSS animations, there is a problem in that you can't rerun animations once they have finished. This poses an issue since we want that nice circle to show up every time we click on our checkbox.

We will use CSS Trick's Restart CSS Animation JavaScript tip to help our animations along.

Basically what this method does is copy the element you want to reanimate, and then it injects it into your HTML while removing the old instance.

Here is the JavaScript to get this working.

// per css-tricks restarting css animations
// http://css-tricks.com/restart-css-animation/
$('label').click(function() {

  // find the first span which is our circle/bubble
  var el = $(this).children('.circle');

  // clone it
  var newone = el.clone(true);  

  // add the cloned version before our original

  // remove the original so that it is ready to run on next click
  $("." + el.attr("class") + ":last").remove();

Now when we click our checkbox, the circle will reappear each time! There's one last problem we have to deal with. Since we styled our label.circle, it takes our animation styling on page load.

Let's make sure it doesn't show our circle on page load since that could be confusing for our users.

Preventing the Circle from Showing On Load

To get rid of showing the circle on load, we will remove the circle class and add that in using JavaScript.

// per css-tricks restarting css animations
// http://css-tricks.com/restart-css-animation/
$('label').click(function() {

  // find the first span which is our circle/bubble
  var el = $(this).children('span:first-child');

  // add the bubble class (we do this so it doesnt show on page load)

  // clone it
  var newone = el.clone(true);  

  // add the cloned version before our original

  // remove the original so that it is ready to run on next click
  $("." + el.attr("class") + ":last").remove();

Now our circle only animates when we want it to.


With a few different CSS techniques like pseudo elements, transitions, and animations, we have created a beautiful checkbox that is interactive and gives our users something different than they are normally used to.

With so much of the new tools coming out being interactive like Polymer it's a great place to look for inspiration when creating new and exciting things with the tools we are familiar with.

In the future we'll look at actually using Polymer and how it does things using Web Components and we'll also explore more of the elements it has and recreate those in CSS.

Like this article? Follow @chris__sev on Twitter