It’s Time to Fix CSS Animation Keyframes & Timing

Miles Sebesta
May 16 · 7 min read

First, I love animation. And I love the growing field of CSS animation. But the reality is vanilla CSS animation has, and will always have, major limitations because of how the code is written.

Animation is not :hover effects. That is movement and movement is not animation, it is movement.

The word stems from the Latin word animātiō which translates into “bestowing of life”. A powerful definition that has driven years of discovery.

Today animators employ two different workflow techniques to breathe life into their work: Straight Ahead or Pose to Pose.

Straight ahead animation is a technique that brings organic life to an animation. You have probably used this technique if you ever made flip-books as a kid while you were bored in class. Straight ahead allows animators to be spontaneous with their drawings, think the flow of conscious writing, or jazz improvisation.

Let’s say an animator is tasked with drawing a person skateboarding from the left of the frame to the right. Utilizing a straight ahead workflow, the animator first starts drawing the first frame on the left, they know they have to go to the right, but they don’t know how they are going to get there yet. Maybe they have the person jump over a box, or does a crazy flip? The possibilities are endless.

Through straight ahead the animator discovers how they reach the end while drawing. Not fully planning or thinking head but just allowing the shapes to flow from drawing to drawing.

Pose to pose focuses on hitting significant poses at specific times. These key poses, or key drawings, in a sequence are what we now call keyframes, key poses, or just keys. In this workflow, an animator first draws and refines the major moments in a scene. They then continue to break down the movement with inbetweens “tweens”. This process gives the animator more control of the final result. It opens up space for animators to push the key moments while keeping a story on track.

Traditionally senior animators would draw the keyframes, and use a dope sheet, to indicate movement to a more junior animator, called a “tweener”.

Tweeners fill in the gaps of animation. Today computers do this job. In programs like Maya, animators animate keyframes, while allowing the computer to tween, or fill in the gap.

For a more visual example, check out this video.

Now the critique…

Coding vanilla CSS Animation through a true pose to pose animation technique is incredibly hard. This reality will always limit what can be accomplished through hand-written CSS Animation.

One reason, the lack of a universal clock/constant/measurement.

The constant for film is 24 frames per second. Every second of animation has twenty-four drawings or 24 frames. Arms, feet, hands, speech, everything happens at 24 frames per second. Life happens at 24 fps; this is the constant. It serves as an internal clock for featured film animators.

This universal constant allows animators to measure sophisticated movements but more importantly communicate and grow. Life is broken down into single frames, 1/24th of a second at a time.

Saying that scene needs 3–4 more frames to breath, means the animation is about 0.25 of a second off. Or push this pause and hold it for 12, means stretch the pause out to half a second. Time is paired with the art itself and is embedded in the language.

For CSS animation time doesn’t exist. There is no universal measurement of time, everything is a percentage.

For example, let’s say we want to grow an object, using keyframes we would write something like this:

In traditional film, we know a single keyframe is 1/24 a second. But in CSS what does 50% of keyframes mean? Does it mean 50% of a second? Or 50% of 10 seconds? There is no constant.

CSS decouples animation with one of its most important principles: timing.

Timing is a key factor in great animation and yet CSS throws it out the window. Timing was so important that early Disney masters extensively write about it and dubbed it as one of the 12 principles of animation.

The 12 principles help animators describe, observe, and master the understandings of the basic laws of physics through drawing. (I included a video that highlights these principles for those interested)

CSS keyframes have no true indication of time, only a fluid percentage point. The perceived effect of the code above is drastically different if it is running on a 1-second animation rate or 10-seconds.

The fluidity of percentages makes it extremely hard to really fine-tune micro-movements and this is a big problem.

Seasoned animators can spot issues where timing is off by microseconds, and so can viewers. To viewers, unproperly timed animation feels weightless and lifeless. Viewers might not be able to describe why the animation feels off, they just instinctually know it is off. The animation doesn’t represent the physical world they know. Sure we can write some fancy SCSS mixins and functions like:


To produce wackiness like this as an attempt to create somewhat of a constant and help our timing issues:

But this still has its limitations, the ones that are inherent with CSS animation. The code becomes exponentially complex when you add multiple objects interacting with each other. The majority of this complexity, troubleshooting the chaining together of sequence timings and delays across multiple objects.

You start to experience these problems with simple tests like a classic bouncing ball test.

Which becomes increasingly frustrating as you try to get slightly more complex movements, that are laughably simplistic to animators.

You have to go through great lengths to not only chain together animations, but more importantly, figure out a way to sync them. Case and point:

The battle against timing forces us to figure out an animation through a straight ahead methodology. Because we don’t have the ability to easily freeze and sequence through keyframes we naturally work on feature by feature. Slowly adding more and more, rather than truly pausing on key moments. Meaning, if we were to animate a bouncing ball first we might animate the left and right movement, then work on the height, then work on the squash and stretch. Rather than focusing on the extreme keys.

For native, hand-written, CSS animation to fully mature we need to recouple animation to timing. I believe this can be done by:

  1. Deciding on universal time unit, example 10th of a second or milliseconds.
  2. Baking the universal time unit into “keyframing”.

This would allow us to move from code like:

To something like:

Or even:

I believe this would make it drastically easier for designers to create interaction between objects.

To really take it to the next level we can then.

  1. Develop the ability to “scrub” or flip back and forth between keyframes which would allow us to utilize a Pose to Pose workflow.
  2. Develop JS libraries for joints and changing (both IK & FK).

But both of these points are nearly pointless till we decide to recouple timing to animation.

Till then programs like hype3 might be our only hope for more complex, story-telling, animations. But that discussion is another post.

Moral of the story, I love animation. I want to see animation mature more through HTML, CSS, and JS. But before that can happen, I really believe there are some changes that are needed, specifically with timing.

If nothing changes CSS animation will always struggle to move far beyond just being arbitrary movement.

If you read this post please clap it motivates me to keep writing. Also, I would love to hear your thoughts and feedback.

Miles Sebesta

Written by

Full Stack Developer with a degree in digital finger painting. Working my dream job as a classroom consultant; training students in seo and frontend design

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade