Writing CSS animations, cleanly

Quick intro to how I write animations in css

Reimagining my workflow is something I am constantly doing by experimenting with new techniques, tools, etc. Lately I’ve been writing my CSS animations in a couple of different ways, and I just want to quickly share the method I’ve come to like the most.

Setup

While I’ve also been experimenting with a few different text editors (more on that later), I write everything in Sublime Text 3, and in Sass. Writing in Sass is important for how I control my animations—you’ll see why later.

Also, it doesn’t hurt to have something writing browser prefixes for you. I use Gulp, or Codekit for that. For quick testing, I find it extremely helpful to open up a pen in Codepen and turn on auto-prefixing, it is a serious time saver.

Base variables

The way I work is by defining a base animation style (and transition style) that I will use across all elements, through a couple of variables. Coming from a strong appreciation and education in animation, I find custom bezier curves are necessary for really engaging motion.
I like to use @LeaVerou’s, bezier-curve.com to test and determine my curves, then I create base animation variables:

$base-curve: cubic-bezier(.06,.55,.9,.98);
$base-transition: all 200ms $base-curve;
$base-animation: infinite $base-curve alternate forwards;

The values can vary depending on the application, and I generally have $base-curve1, $base-curve2, etc. to define a couple different situations.

There are a number of benefits to defining the curve, and in some cases is more useful than defining a base transition. I find myself fine tuning my bezier curves a lot to get it right and changing one variable is easier and quicker than the traditional, inline method.

To apply the transition, or animation to an element, I simply need to write

.element{
     transition:$base-transition;
     opacity:1;

     &:hover{
     opacity: 0.8;
     }
}

What I like most about using transition: $base-transitionis the variable only defines a few of the base transition properties. The base properties can be the extent of the transition, or they can be modified & added to.

Keyframes

When using keyframe animation, I use the $base-animation variable to quickly add my animation properties. Since the animation name or duration is not defined(for flexibility!), they are written before the variable:

.element{
     animation:animationName 500ms $base-animation;
}

This way, I can add on, or overwrite certain aspects of the base-animation with direct property values, e.g, changing the animation-duration by adding a direct value below the animation call:

.element{
     animation:animationName 500ms $base-animation;
     animation-duration: 200ms;
}

Mixins

I’ll try to keep this simple, since the goal is to speed up writing animations. For simple motions and animations that I know I will be using often–and when I’m not using auto-prefixer—I will write simple mixin that includes the following:

@mixin move-horizontal($xvalue){
     transform: translateX($xvalue);
     -webkit-transform: translateX($xvalue);
}

which I can then call easily with:

.element{
     transition:$base-transition;
    
     &:hover{
          @include move-horizontal(100px);
     }
}

Lastly, I find it quick, and useful to use these mixin within keyframes, which can be done like so

     
.move-right{
     animation:moveRight 500ms $base-animation
}

@keyframes moveRight{
     0%{@include move-horizontal(0px)}
     100%{@include move-horizontal(200px)}
}

OR
it can be useful to define more complex keyframe animations that have a bit of flexibility, like the following:

@mixin slide-in-x($origin,$destination){
     0%{
          -web-kit-transform:translateX($origin);
          transform:translateX($origin);
          opacity: $origin;
     }
     100%{
          -web-kit-transform:translateX($destination);
          transform:translateX($destination);
          opacity: 1;
     }
}
/*which can be added as keyframes by including it */

 @keyframes slideLeft{
     @include slide-in-x(-100px,0);
}

/* then call this animation with: */
.slideInFromLeft{
     animation: slideLeft 200ms $base-animation;
     animation-iteration-count:1;
     
}

See the Pen xbzjOq by Genki Hagata (@hagata) on CodePen.

I’ve added a short list of useful animation extensions like these here in this gist. My favorites are @import size which is extremely useful for SVG’s, even when they’re not animated, & @import origin.

I hope you can start to write your animations this way to keep your code nice and clean, or at least be inspired to do your own thing from this.

Learning Resources