Animating With Minimal CSS and SVGs

For when JavaScript is just a bit too much for you right now

A recent project I was working on found me using a lot of radio buttons and checkboxes, but they did not fit the aesthetic of my site at all. I poked around the web a lot for ways to change these buttons, but most solutions I found used JavaScript, which I hadn’t yet begun to learn, or just an endless style sheet that would take days for me to decipher.

No Thank You!


The first thing I learned about on my journey for not-ugly checkboxes was CSS transitions. This allows the different parts of the website to transition between two states with some animation effects. Here’s the font-size effect:


The code is pretty simple:

.check_label {
transition: font-size 1s ease;
font-size: 1em;
input:checked ~ .check_label {
font-size: 2em;

On click the font size of the checkbox label increases to 2em, and it does so over the course of a second. Pretty smooth.

Interesting, but it’s not too pretty yet. I don’t like that grey checkbox! The styling options are so limited when it comes to the box, so much so that the general recommendation is to hide the box and style the label to behave as a checkbox. That involved a lot of extra CSS.

Adding SVGs

Then I discovered how I could use SVGs to bypass the visual part of the CSS. As someone who like to use Adobe Illustrator for fun, this seemed like the perfect solution for me.

This involved two major steps:

  1. Draw the assets. This one may sound a bit daunting for anyone who isn’t familiar with vector illustration programs, but you can find plenty of beautiful SVGs online at places like The Noun Project.
  2. Animate them! This was a feature I did not realize CSS had, but it’s immensely flexible and allows for some very cool dynamic effects on the page without javascript.

The animation step is what threw me for a loop, but it’s actually incredibly simple — all you need to do is give a before state, an after state, and the CSS transition tag, like before.

The HTML is below — the SVG tag holds my actual SVG code, which was copy and pasted from my SVG file opened in my text editor.

<input id="checkBox" type="checkbox">
<label for="checkBox">
<g id="Label"></g>
<g id="Check" class="appear"></g>

The label associated with the checkbox can be clicked to change the “checked” status of the checkbox. This means that we can get rid of the actual checkbox and just style the label!

So in the CSS we do this to hide it and get rid of the hover effect:

input {
position: absolute;
opacity: 0;
cursor: pointer;

Next, we want to animate our checkmark. To do this, we use the CSS transition tag.

label .appear {
opacity: 0;
transition: opacity .5s ease;
input:checked ~ label .appear {
animation: opacity .5s ease;
opacity: 1;

First, we set the checkmark’s opacity to 0 so that the box will appear unchecked. Then, any “.appear” that immediately follows (via the CSS ~ selector) a checked input box will be given an opacity of 1.

The transition tag says that the opacity will transition over .5 seconds and ease into the beginning and ending of the transition.

This ends up looking like:

Much prettier!


Another animation technique I discovered is CSS Keyframes. Anyone who has spent some time in a video editing software should be familiar with the timeline, which is the duration of a video. Keyframes are individual points on that timeline with different states assigned to an object.

In the case of CSS, this can look like this:

@keyframes rotate-tire {
0% {transform: rotate(0deg)}
100% {transform: rotate(359deg)}

At the beginning of our timeline (0%) our object is rotated 0 degrees, and at the end of the timeline it is rotated (100%).

We can then apply this to an object the same way we did with transitions before:

.tire {
animation: rotate-tire .25s linear infinite;
transform-origin: 50% 50%;

Our tire class animates with the above rotate-tire @keyframes, over the course of .25 seconds, and instead of easing it will go at a linear speed, and it will continue infinitely.

Now we just need an SVG of a car with some tires with the class of “.tire” and we can see it start driving!

Keyframes can do a whole lot more than just rotating — and it’s all done through just CSS.

Like what you read? Give David Brennan a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.