CSS Animation Tricks: State Jumping, Negative Delays, Animating Origin, and More

Avatar of Zach Saucier
Zach Saucier on (Updated on )

I’ve fallen into the habit of creating CSS animations in my free time, inspired by things I come across during the day. To create the animations as I imagine them using as few elements as possible, I’ve found some tricks to make CSS do things you might not know it could do. I’d like to share them with you.

#1) Jump to another state mid-animation

CSS animation makes it easy to transition properties to a new value over time. They also have the ability to jump properties to a new value virtually instantly. The trick is to use two keyframes with a very small difference, around .001% works well.

@keyframes toggleOpacity {
  50% { opacity: 1; } /* Turn off */
  50.001% { opacity: 0.4; }

  /* Keep off state for a short period */

  52.999% { opacity: 0.4; } /* Turn back on */
  53% { opacity: 1; }
}

The following is an extreme example of this, toggling opacity and a text-shadow to mimic a flickering billboard light.

See the Pen No Vacancy 404 CSS Only by Zach Saucier (@Zeaklous) on CodePen.

#2) Negative animation delays

A positive animation delay is where the animation waits a certain amount of time to begin. A negative animation delay starts the animation immediately, as if that amount of time has already gone by. In other words, start the animation at a state further into the animation cycle. This allows animations to be reused across several elements, given all that needs changing is the timing.

Here is an example of that where each circle begins immediately at a different state in the animation cycle:

See the Pen Circle Snake by Zach Saucier (@Zeaklous) on CodePen

#3) Proportional animations

I try to make everything that I put into production be as responsive as possible, including my animations. Responsiveness for CSS animations is not possible for all animations I have created, but sometimes it is, using percentages and other relative units.

In many of my animations, I use elements like circles and squares which need the a proportional width and height. You might think I need to use fixed width & height values to keep them that way, but that’s not the case! I am able to create them using a percentage width, zero height, and percentage padding. The padding-bottom is the trick to keep it proportional to the width, like this:

.container {
  position: relative;
  display: block;
  width: 100%;
  height: 0;
  padding-bottom: 100%;
}

You can see this in practice on the following demo by changing the size of the window it is in. The demo also makes use of negative animation delays.

See the Pen Responsive CSS bars by Zach Saucier (@Zeaklous) on CodePen.

#4) Changing transform-origin mid-animation

While working on one of my animations, I was surprised to find out that not only can transformation-origin be changed mid-animation, it is also animatable! In the example below, this allows us to create one animation using rotations on different axes instead of using four separate animations.

See the Pen Change transformation-origin mid animation by Zach Saucier (@Zeaklous) on CodePen

The downside to this trick is that you can’t use animation-mode: forwards; for only a part of an animation. This means that we have to re-position the element to an equivalent of its state before applying the change in transformation-origin. In the above example, this is done by using translates to mimic the rotation’s effects. However, this technique can get tedious on more complex examples, as seen here.

#5) Negative transform-origins

You are able to set a negative transform-origin, which is useful for things like creating circular movement paths. Instead of specifying specific translate and rotation values using one element to create circular animations as Lea Verou describes, we can do it much more simply by using negative transform-origin values in addition to a second element or pseudo-element (one element if we want the element to rotate as well as move in a circular path). By using varying values of a negative transform origin, we can reuse the same animation for multiple elements while still retaining circular motion for each.

See the Pen CSS Circular Motion Technique by Zach Saucier (@Zeaklous) on CodePen.

#6) Box shadow magic

For animations of simple no-content shapes, box-shadow is quite useful. The box-shadow property can create multiple borders around elements. That idea, combined with some displacement, can create new animatable “elements” out of no additional HTML elements. This enables us to create the following animation, which appears to be six circular elements rotating circularly, but is in fact one element with some offset box-shadow shapes.

See the Pen Single element color loader by Zach Saucier (@Zeaklous) on CodePen

Sadly, percents are not supported by any box-shadow properties so they are not as easily responsive as a native HTML element. However they can still be changed manually in an animation or by using transform:scale(n) on the actual HTML element which they are a part of.

#7) Using pseudo-elements

Similarly with box-shadows, pseudo elements can be used to add more content to the appearance of a single element. They can have separate animations from their parent, their own box-shadows, and are very similar to being child elements of without the HTML markup. This let’s us create amazing single element creations like the one below.

See the Pen Single Element gif Recreation by Zach Saucier (@Zeaklous) on CodePen

In the example, all of the large circles around the middle flashing circle, as well as two of the smaller circles on the rim (opposite from each other) are box-shadows on the main element. The other two small circles are part of a pseudo-element’s box-shadow and the ring made of dashes is an SVG applied as a background on the other pseudo element.

Some other things to note

Use transforms when you can

Transforms perform better than their non-transform counterparts as Paul Irish has shown (also). Primarily this means using scale and translate over changing the dimensions or top/left values.

Transforms also allow for more responsive design, allowing things such as scale to be used relative to their original size, as is shown in this animation by Amos.

Not using transforms can also cause problems that are hard to catch. For example, in this animation of mine the elements were being colored incorrectly in Chrome although the values themselves were correct. After switching it to use transforms all my problems were solved.

z-index can cause problems

I probably spend more time fixing z-index issues with my animations more than any other issue. Z-indexes are handled differently from vendor to vendor. In animations, the primary difference is that Mozilla does not animate z-index values, they have elements jump from one z-index to the next, whereas vendors like webkit do animate the z-index value.

Another thing to note is that if one wants their pseudo elements to appear behind their parent element, the pseudo element must have a negative z-index and the parent cannot have a stacking other than the default, which means you can’t apply a z-index or anything else that takes the parent out of its natural stacking context.

One last trick dealing with z-index is one that deals with opacity. Whenever an element is given an opacity other than the default “1”, it gains its own stacking context. For more information on this, check out Philip Walton’s post

Get inspired

Whether it’s something you see in the real world, an interesting web page that you find online, part of a video intro, a gif, or something else entirely, find things that you think may be possible to create and try to do so!

I have found that not looking at how the original author created it enables me to learn, to create it in a unique style, and sometimes even do it in a more efficient manor. Even if I end up failing at my original intention, I always become more comfortable with or learn more about the language I’m using. Often times I have something to show for it, even if it’s not as grand as I would had originally hoped. Other times I’m completely surprised by how awesome my creation is when I didn’t even mean for it to be!

I hope that this article helps you construct more awesome creations, even if you learned nothing from the specific techniques!