Animating Checkboxes and Radio Buttons with Sprite Sheets

Sprite sheets can be used to create animated checkboxes and radio buttons without any Javascript. Click the checkbox below to see it in action.

Background

A sprite sheet animation is created with a single image containing multiple frames side by side. The image is clipped to show one frame at a time. Changing the clip position from frame to frame creates an illusion of animation.

Typically, sprite sheet animations are created in HTML by using the sheet as a background image and then moving the background position to reveal different frames. The sprite sheet must be made of equal-sized frames arranged in a single row or column. Below you can see a sprite sheet with 11 frames in a row. Each frame is 50px × 50px.

Star sprite sheet

Only one frame is show at a time by clipping the background image. The clipping is shown by the blue rectangle below. Move the slider to see how the background position affects which frame is shown inside the clipping rectangle. The background image is repeated. The first frame would show up again if the background position value gets too high. The image below is 550px wide (11 × 50px), so -500px is the position of the last frame.

background-position: 0px

The sprite sheet can be a PNG or SVG image. The benefit of PNG is that it looks the same in all browsers. The benefit of SVG is that it is resolution independent and stays crisp if the page is zoomed in or is shown on HiDPI screens.

Sprite sheets are not the only way to create animations for web pages. CSS animations, CSS transitions, Javascript animations and animated GIFs all have their own use cases. Sprite sheets are good if:

  • a CSS-only solution is desired
  • complex animations are needed (CSS transitions can only display a transition between two values)
  • older browsers need to be supported (sprite sheets work in IE11 and IE10, CSS animation of SVG doesn’t)
  • animation needs to be run when needed (playback of animated GIFs can’t be controlled)

There’s always many ways to do things in HTML and CSS, so you may find alternate ways to style checkboxes and radio buttons. The solution given here is only one option.

Creating Sprite Sheets in Keyshape

You can export PNG or SVG sprite sheets in Keyshape with these steps:

  1. Select the File > Export menu command.
  2. Select either SVG or PNG format.
  3. Select Sprite Sheet as the animation type.
  4. Choose the begin and end times. Usually, the defaults values are good here.
  5. Choose the frame rate. Usually, the default frame rate is fine.
  6. Select the algorithm, either Single Row or Single Column.
  7. Press the Export button.

The Keyshape file for the star sprite sheet can be found at the bottom of this page.

When you play back the animation in Keyshape, check the Animation > Stepped Playback option to enable frame-by-frame playback. That ensures that the animation is played back the same way it will look after exporting it as frames.

Checkboxes

Here’s details about the HTML and CSS code needed for animated checkboxes. Here’s again the animated checkbox.

The HTML code for the checkbox looks like this:

<input id="my-checkbox-id" class="my-checkbox" type="checkbox"><span></span> <label for="my-checkbox-id">Animated Checkbox</label>

HTML

The checkbox could be styled directly, but some browsers don’t support it. So, there’s an extra <span> element after the input element to display the animation. The <label> element is optional. Remember to consider accessibility if you leave the label element out.

The idea is that the input element is made invisible by changing its opacity. That hides it, but keeps it accessible for focusing and screen readers. Then, the span element is moved over the input element and styled with a background image. The span element width and height are set to the size of one frame to clip the background image. When the checkbox is checked, the background position is animated in steps to the last frame position.

The CSS code to style the checkbox is shown below with comments. When you use this with your own sprite sheets, you need to change some of the values:

  • Change all widths and heights to match the exported document size (50px × 50px in this example)
  • Change the background url to point to your sprite sheet image
  • Change background-position to the exported sheet width minus one frame size (550px - 50px = 500px in this example, the value needs to be negative: -500px)
  • Change the transition time to the exported end time (0.5s in this example)
  • Change the transition steps to the total frame count minus one (11 - 1 = 10 in this example)
.my-checkbox {              /* styles for the checkbox */
width: 50px; /* CHANGE this to your document width */
height: 50px; /* CHANGE this to your document height */
opacity: 0; /* this hides the native checkbox */
vertical-align: middle; /* used to align checkbox with label */
}
.my-checkbox+span { /* styles the span element after the checkbox */
background: url('my-sheet.svg'); /* CHANGE this to point to your image */
width: 50px; /* CHANGE this to your document width */
height: 50px; /* CHANGE this to your document height */
margin-left: -50px; /* CHANGE this to your document width, this moves span element over checkbox */
display: inline-block; /* this is needed to get width, height and margin functional */
pointer-events: none; /* this passes mouse clicks through to underlying checkbox */
vertical-align: middle; /* used to align checkbox with label */
}
.my-checkbox:checked+span { /* styles the checkbox checked state */
background-position: -500px; /* CHANGE to sprite sheet width minus one frame size */
transition: background-position 0.5s steps(10, start); /* CHANGE time and steps */
}
.my-checkbox:focus+span { /* focus style for keyboard users */
outline: 2px solid #87ceeb;
}

CSS

Note that the above doesn’t include a style for a disabled state and it should be added if needed.

Radio Buttons

Radio buttons can be styled the same way as checkboxes. Here’s three buttons with the star animation.




Here’s the HTML code for the radio buttons:

<input id="my-radio-1" class="my-radio" type="radio" name="my-group"><span></span> <label for="my-radio-1">First</label><br>
<input id="my-radio-2" class="my-radio" type="radio" name="my-group"><span></span> <label for="my-radio-2">Second</label><br>
<input id="my-radio-3" class="my-radio" type="radio" name="my-group"><span></span> <label for="my-radio-3">Third</label><br>

HTML

Again, the native radio buttons are made invisible and an extra <span> element is placed over them to display the animation. The label element is optional, but remember accessibility if you leave it out.

The CSS code to style the radio buttons is shown below with comments. When you use this with your own sprite sheets, you need to change some of the values:

  • Change all widths and heights to match the exported document size (50px × 50px in this example)
  • Change the background url to point to your sprite sheet image
  • Change background-position to the exported sheet width minus one frame size (550px - 50px = 500px in this example, the value needs to be negative: -500px)
  • Change the transition time to the exported end time (0.5s in this example)
  • Change the transition steps to the total frame count minus one (11 - 1 = 10 in this example)
.my-radio {           /* styles for the radio button */
width: 50px; /* CHANGE this to your document width */
height: 50px; /* CHANGE this to your document height */
opacity: 0; /* this hides the native radio button */
vertical-align: middle; /* used to align radio button with label */
}
.my-radio+span { /* styles the span element after the radio button */
background: url('my-sheet.svg'); /* CHANGE this to point to your image */
width: 50px; /* CHANGE this to your document width */
height: 50px; /* CHANGE this to your document height */
margin-left: -50px; /* CHANGE this to your document width, this moves span element over radio button */
display: inline-block; /* this is needed to get width, height and margin functional */
pointer-events: none; /* this passes mouse clicks through to underlying radio button */
vertical-align: middle; /* used to align radio button with label */
}
.my-radio:checked+span { /* styles the radio button checked state */
background-position: -500px; /* CHANGE to sprite sheet width minus one frame width */
transition: background-position 0.5s steps(10, start); /* CHANGE time and steps */
}
.my-radio:focus+span { /* focus style for keyboard users */
outline: 2px solid #87ceeb;
}

CSS

Vertical Sprite Sheets

Frames in a sprite sheet can be in a row or a column. You can change the CSS code to use columns by changing the background position to move the Y coordinate:

.my-radio:checked+span {
background-position: 0px -500px;
transition: background-position 0.5s steps(10, start);
}

CSS

Accessibility

If you have a checkbox or radio button without a label, then you should use an aria-label attribute to describe the meaning of the button. Normal browsers won’t display aria-label, but assistive technologies, such as screen readers, can use it. Here’s examples:

<input id="my-favorite-checkbox" class="my-checkbox" type="checkbox" aria-label="Favorite item"><span></span>
 
<input id="my-radio-1" class="my-radio" type="radio" name="my-group" aria-label="Star Radio Button"><span></span>

HTML

The Future: Direct Styling of Checkboxes and Radio Buttons

It is possible to directly style checkboxes and radio buttons without extra span elements. It happens by setting their appearance property to none. It removes the native look and allows background images to be used instead. Here’s an example:

The HTML code for it doesn’t have extra span elements:

<input id="my-checkbox2-id" class="my-checkbox2" type="checkbox"><label for="my-checkbox2-id">Animated Checkbox</label>

HTML

And the CSS code is simpler:

.my-checkbox2 {
background: url('my-sheet.svg');
width: 50px;
height: 50px;
appearance: none; /* removes native look of the checkbox */
vertical-align: middle;
}
.my-checkbox2:checked { /* styles the checkbox checked state */
background-position: -500px;
transition: background-position 0.5s steps(10, start);
}

CSS

As you can see, the code is very clean. Extra <span> elements aren’t needed and the style applies directly to the checkbox. Also, there’s no need for extra rules for the focus outline.

However, Firefox 53 has a bug, which doesn’t remove the native styling completely. Also, Internet Explorer 11 doesn’t support the appearance property.

So, it is safer to use a <span> element to style the controls until Firefox and Internet Explorer get sorted out.

Keyshape Files

Document History

- Changed to use classes for styling.
- Document created.