A design pattern for making interesting CSS animations in under 10 minutes

“the way is long if one follows precepts, but short and helpful, if one follows patterns” ― Lucius Annaeus Seneca

I’ve had a lot of fun making a certain style of CSS animation demos on CodePen lately, all of which seem to follow a similar design pattern. Below are a couple of examples (embedded here as .gifs, but click through to see the live HTML/CSS versions):

Unnamed penorbit

Rainbow Black Hole Sun

A Sass and CSS animation experiment

I don’t know whether a legitimate use case exists for animations like these, and that’s 100% okay by me. Exploring your creative side and stretching the limits of what you can do with HTML, CSS, Sass, Javascript, canvas, SVG, etc. has plenty of value in itself. Plus I find it relaxing, almost soothing sometimes, to spend a little time experimenting and playing around with no specific end goal driving the process.

A note on CodePen

From the About CodePen page: “CodePen is a playground for the front end side of the web. It’s all about inspiration, education, and sharing.”

CodePen really lowers the barrier to entry for exploring front-end techniques, and makes it pretty frictionless to just try things out. With the click of a checkbox you can enable “prefix-free” mode, freeing you to write standard unprefixed CSS properties, and CodePen inserts all the necessary vendor prefixes (e.g. -moz, -webkit, etc) for you. The toggle of a button switches you from HTML to HAML, another button switches you from CSS to Sass, or SCSS, or LESS, and so on. It’s perfect for painless experimentation, so if you’ve never used it you should go try it out right now!

Here’s the trick

There’s a simple pattern I followed with all of the above examples. It’s basically this:

  1. Generate X number of elements with HAML
  2. Apply some basic styling to all of those elements
  3. Create a loop in Sass
  4. Inside of the loop, use the :nth-child or :nth-of-type pseudo selector to create a slightly different style for each element. That often means a different color, a different transform property, a different keyframe animation, or in some cases the same animation but a different animation-delay for each element
  5. Then all that’s left is just to play around with different transforms and animation properties, to see what looks cool or interesting

Diving in to the markup: 1 minute

Screen Shot 2013-11-03 at 8.33.57 PM
Enabling HAML in CodePen, what could be easier?

Let’s build an example project using this pattern. The first thing you will want to do is generate some number of html elements to work with. For this example, let’s make 100 divs, just because 100 is a nice round number, not too big and not too small, and the div is the go-to generic block element. I’m going to use HAML for this because it’s nice and quick, but there’s no reason you just couldn’t type in <div></div> a hundred times if that’s more your style. To use HAML in the real world you have to install Ruby, then install HAML as a ruby gem, then I don’t know what else… in CodePen to use HAML you just click the little gear icon at the top left of the HTML panel, then click the big button that says HAML. Then insert the two lines below, and that’s your 100 divs.

[ruby]
-(1..100).each do
%div
[/ruby]

Technically that’s a block of Ruby, and it creates a “range” from 1-100, and then iterates through each number in the range, creating a div for each one. But do you need to know Ruby or HAML to do this? I don’t! As long as you can use the snippet above you’re golden for now. Here’s a quick little intro to HAML if you want to learn more about that.

Applying some basic styles: 1.5 minutes

Okay so I allotted 90 seconds for this step, but once you’ve done it a time or two you could probably type it in 45 seconds :)

[css]
body{
background: #111;
}
div{
height: 20px;
width: 20px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -10px;
margin-left: -10px;
border-radius: 3px;
}
[/css]

What’s happening here is we’re making the divs into 20px square blocks, then positioning them all absolutely in the exact middle of the screen using this old technique. Because they are all absolutely positioned, they will all be stacked up one atop the other like a deck of cards.

The basic Sass loop: 2 minutes

Screen Shot 2013-11-03 at 9.25.33 PM
Enabling Sass. Go ahead and click “reset” and “prefix-free” while you’re in there.

Now you’re going to want to turn on Sass, using the .scss syntax, using the same “click the gear” method that we used to turn on HAML. Go ahead and click “Reset” and “Prefix free” while you’re in there, it’ll make writing animations and transforms much quicker in a minute here :)

Once you’ve got that done, we’ll use the code below to create a @for loop in Sass. Here’s a crash course in Sass control directives, if you really must know more (and eventually you will want to), but all you need for this is the code below. The $i is the iterator variable, and the loop will go from 1 through 100, and $i will increment each time (the first time through $i = 1, then $i = 2, then $i = 3, and so on).

Inside of the @for loop, we use the :nth-of-type pseudo-class with $i passed in as the argument.

[css]
@for $i from 1 through 100{
div:nth-of-type(#{$i}){
/* interesting stuff goes here */
}
}
[/css]

When the Sass is compiled (or transpiled) to CSS, it’ll look like this:

[css]
div:nth-of-type(1}){
/* interesting stuff goes here */
}
div:nth-of-type(2){
/* interesting stuff goes here */
}
div:nth-of-type(3){
/* interesting stuff goes here */
}
… and so on …
[/css]

The interesting parts: 5.5 minutes

This is where you’ll spend the most time playing with options and tweaking numbers. By this point you’ve got the entire necessary structure in place, but what you put inside the Sass @for loop will determine how the final product will look and behave. Here’s the code for an example project, take a look and I’ll walk through it line-by-line below.
[css]
@for $i from 1 through 100{
div:nth-of-type(#{$i}){
background: hsla($i*3.6, 90, 50, .8);
animation: shift#{$i} 35s $i*.3+s linear infinite;
}
@keyframes shift#{$i}{
10%{
opacity: 0;
}
20%{
transform:rotate($i*60+deg) translateX($i*5+px) translateY($i*5+px) scale(2);
opacity: 0;
}
}
}
[/css]

Lines 1 and 2 were discussed above, then on line 3 we’ll set a background color for each div. I really like using the HSLA (Hue, Saturation, Lightness, Alpha) color notation here because it’s incredibly easy to manipulate programmatically, including iterating through the entire rainbow. While the saturation and lightness arguments take a number from 1 to 100, and the alpha takes a value between 0 and 1, the hue argument takes a number between 0 and 360 (like degrees on a color wheel), and values above and below will be modulus 360, so you can pass any number in for hue and it’ll produce a color.

Remember that $i is going to be 1 for the first div, 2 for the second div, 3 for the third div, and so on, and that we have 100 divs. By multiplying $i by 3.6 we get full coverage of all the hues of the color spectrum, from 0 to 360 (or really from 3.6 to 363.6, but close enough for me).

Now for the last part, you’re going to want to have a decent grasp on CSS keyframe animations. On line 4 where we specify the animation, we are first giving it a name using shift#{$i}. So we are giving each div its own unique animation, called shift1, shift2, shift3, etc. Then we define a duration of 35 seconds, a delay of $i*.3 so that each div’s animation starts at a different time (.3 seconds, .6 seconds, .9 seconds, etc), an easing function of linear and an iteration-count of infinite.

Starting on line 6 we are defining 100 different keyframe animations, each slightly different, named shift1, shift2, shift3, etc. The last really key part is line 11, which declares a few different transform properties, the first three of which use the $i variable, so they will be different for each div. For the first div it’ll look like this:

[css]
transform:rotate(60deg) translateX(5px) translateY(5px) scale(2);
[/css]

Then for the second div it’ll be:

[css]
transform:rotate(120deg) translateX(10px) translateY(10px) scale(2);
[/css]

And for the third div it’ll be:

[css]
transform:rotate(180deg) translateX(15px) translateY(15px) scale(2);
[/css]

You get the idea. It should make for an interesting effect, let’s check it out below.

CodePen style

Here’s the result on CodePen. But don’t stop here, now the fun part really begins. Try changing the values where the transforms are defined, or the animation timing values. What happens when you tweak this number here or this property there? Feel free to fork the pen below or just start your own from scratch, and if you do please let me know what you come up with, either by commenting here or on twitter (@therealmarklee). And above all, have fun!

Check out this Pen!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.