CSS Animations with only one keyframe

This is a very quick tip, about a pet peeve of mine in almost every CSS animation I see. As you may know, I’m a sucker for reducing the amount of code (as long as it remains human readable of course). I demonstrated a very similar example in my “CSS in the 4th dimension” talk, but I recently realized I never blogged about it (or seen anyone else do so).

Lets assume you have a simple animation of a pounding heart, like so:

@keyframes pound {
	from { transform: none; }
	50% { transform: scale(1.4); }
	to { transform: none; }

.heart {
	/* ... */
	animation: pound .5s infinite;

You can see the problem already: the shrunk heart state is repeated twice in the keyframes (from and to). You probably know you can combine them into one rule, like so:

@keyframes pound {
	from, to { transform: none; }
	50% { transform: scale(1.4); }

What many don’t know, is that you don’t need these two keyframes at all, since they basically replicate the same state as the one in the .heart rule. To quote the CSS Animations spec:

If a 0% or “from” keyframe is not specified, then the user agent constructs a 0% keyframe using the computed values of the properties being animated. If a 100% or “to” keyframe is not specified, then the user agent constructs a 100% keyframe using the computed values of the properties being animated.

Therefore, the code could actually be as simple as:

@keyframes pound {
	50% { transform: scale(1.4); }

This trick is very useful for providing fallbacks that are the same as the first or last keyframe, without having to repeat them in the @keyframes rule. Of course it doesn’t only apply to animations where you only have one keyframe beyond from and/or to. You can omit the from and to keyframes in every animation, when you want them to be the same as the styles that are applied to the element anyway.

Of course, to make this particular animation appear more natural, it would be much more wise to do something like this, still with only one keyframe (the from state is dynamically generated by the browser):

@keyframes pound {
	to { transform: scale(1.4); }

.heart {
	/* ... */
	animation: pound .25s infinite alternate;

which just reverses every even iteration, instead of trying to have both states (shrinking and growing) in the animation. The reason this looks more natural is that animation-direction: alternate; (which is what the alternate keyword does in the animation shorthand) also reverses the timing (easing) function for the reversed iterations. 😉

  • http://www.facebook.com/mar1ly Marily Nika

    That post would have made an awesome CSS Valentine’s Day blog post (nice one Lea)

    • http://lea.verou.me/ Lea Verou

      Haha, you’re right! Although the concept applies to many more kinds of CSS animation.

      • http://www.facebook.com/mar1ly Marily Nika

        yes but the heart sure got my attention much faster! 🙂

        • http://lea.verou.me/ Lea Verou

          And that wasn’t even intentional, LOL!

  • http://rachelnabors.com Rachel Nabors

    Lovely test case! I see a lot of animations that have an unnecessary number of keyframes these days–I’ve made a few myself! But fewer keyframes means less work for you and less to maintain. Relax, let the computer do the math!

  • http://twitter.com/kevinwhinnery Kevin Whinnery

    Nice tip! Wasn’t aware of the default behaviors.

  • http://twitter.com/donvodki ♠ DONVODKI

    pretty awesome. thanks Lea!

  • http://twitter.com/AllThingsSmitty Matt Smith


  • http://www.facebook.com/cezar.espinola Cezar Sá Espinola

    For the last example you say that you’re going to use animation-direction: reverse, but the example actually uses animation-direction: alternate which reverses the animation only after it plays as normal first.

    • http://lea.verou.me/ Lea Verou

      Good catch! Fixed! Thanks!

  • criography

    I heart (no pun intended;) the way your posts make me feel dumb(;
    Nice tip!

  • http://twitter.com/zinxcombr Zinx.com.br

    Good one!! Thanks.

  • Guest

    So we can make a different heart animation for every human person with CSS by knowing his pulse 🙂

  • http://www.paulund.co.uk/ Paul

    This is great stuff didn’t know that CSS would just reset to the defined class, now you say it that behaviour seems so obvious.

  • maxw3st

    Here’s a christmas card using two of Lea’s CSS tips & tricks. http://sabaki.aisites.com/christmas/christmastree2.html

  • Pingback: CSS3:Animations 实现心跳动画写法 — DBPOO's Blog()

  • Pingback: Bruce Lawson’s personal site  : Reading List()

  • http://twitter.com/simurai simurai

    It would be even more useful if the from/to value actually would be dynamic. For example if you would add

    .heart:hover { transform: scale(.5); }

    it should animate from .5 to 1.4, but instead it keeps animating from 1 to 1.4. Not sure if this is a technical limitation so it doesn’t have to check the values all the time and performance is better.

  • http://qwertjsblog.altervista.org/ Qwertj

    Nice tip!
    I see the last example with some flickering, while the others run smoothly
    I think that’s why when it reverses animation he repaint the heart from the start, without rescale it back.

  • Nora Brown

    Wow — dabblet is amazing. I don’t have to leave your post to fiddle with the examples and create a slow pulsing blue heart instead. Totally delightful!

  • Pingback: Weekly Design News – Resources, Tutorials and Freebies (N.163) | Wordpress Webdesigner()

  • Pingback: Tweet Parade (no.50 Dec 2012) | gonzoblog()

  • Pingback: Today’s Readings | Aaron T. Grogg()

  • Pingback: Пингвин Рыба Есть » Список для чтения()

  • Josep Crespo Santacreu

    The animations do not work with the latest version of “Google Chrome”. What has changed to make it happen? Is there a solution?

    PS. Connect with “Facebook” or “Google+” do not work.

    • http://lea.verou.me/ Lea Verou

      Works fine for me, in the latest versions of both Chrome and Chrome Canary.

      Regarding Facebook or Google+ connect, you must be referring to DISQUS. I’m not using any of those.

      • Jotace

        I have Windows 7 and Canary Versión 27.0.1425.2 and Chrome Versión 25.0.1364.97 m the animation do not work for me 🙁

        • http://lea.verou.me/ Lea Verou

          Just tested in Windows too, through browserstack. Still works.

      • Juan Calderón

        Also I tried the code on dabblet in Canary Versión 27.0.1425.2 and Chrome Versión 25.0.1364.97 m, the animation still doesn’t working for me 🙁

  • Pingback: Weekly Design News (N.163)()

  • Pingback: 20+ New CSS Tutorials | Splashnology()

  • SAM3R

    Why did you use ” display: inline-block; ” ?

  • Pingback: Animación de corazón CSS3 usando keyframe - Blog mundosica.com()

  • Pingback: 20 Best New CSS Tutorials | HueDesigner()

  • Pingback: 27 Fresh CSS3 Tutorials()

  • Pingback: 27 Fresh CSS3 Tutorials - Dg3World()

  • Pingback: quicktip CSS-Code einsparen bei den css-Animationen | CSS3.de()

  • http://twitter.com/luso11 Luis Alonso

    Thank you for posting this, but i have a question. How is it possible that the animation is working on this website but not working when i copy-paste the code?

    • http://lea.verou.me/ Lea Verou

      You’re missing the necessary prefixes (or just use prefixfree, that’s what’s used in the above examples)

  • Daniel Smith

    love your blog, lots of great info on here!

  • http://www.y8u.org/ Y8 Games

    This is an outstanding informational article. I even have very enjoyed reading your views and thoughts on this subject. you’ve got got given Pine Tree State things to ponder.

  • ninjamoves

    does @keyframes on css3 adopted the physics from cornaSDk

  • RT

    Was browsing along and noticed I’ve been getting tips from hot female web designers.

    Why can’t I work with hot female web designers!?

  • Peter L

    This was a nice idea but unfortunately I discovered that not all user-agents construct styles for the omitted keyframes, for example IE10. For animations to work properly in all browsers, you must still specify ALL the keyframes and ALL the properties you wish to animate. For more details see this article: http://www.sitepoint.com/animation-keyframe-gotcha/

    • http://lea.verou.me/ Lea Verou

      Your recommendation is like using a sledgehammer to push a button. The issue only applies to cases like the one you mentioned, where you’re using the initial value for those keyframes and a certain browser’s initial value is not animatable. For example, this works fine in IE10: http://dabblet.com/gist/6894938

      You can’t ignore this issue by just specifying all keyframes, it will come back to bite you in other cases, e.g. transitions.

      • Peter L

        I don’t understand what you mean by ignore, but it certainly *solves* the issue. There is no downside to specifying all the keyframes, other than adding a few more bytes to your stylesheet. If someone gets into the habit of not specifying all the keyframes (like I did) without knowing the potential problems with some properties such as box-shadow, text-shadow, (I’m guessing there’s more). They’ll be wondering why their animation is not working properly. And the answer is because they omitted some keyframes and didn’t specify values for the properties they wish to animate. It should be taken into account at least.

        For those obsessed with saving a few bytes on their stylesheet, you can omit keyframes for -webkit-, -moz-, and -o- prefixes but for IE10 + IE11 you must write all the keyframes 0% – 100% and in each of those keyframes – state the properties you wish to animate and state the values you want. (e.g. just 100% { text-shadow: 10px 10px #ddd; } will not animate. But also including 0% { text-shadow 0 0 #ddd; } will make it animate).

        And you’ll never know how future browsers might behave, so it’s safest just to simply write all the keyframes anyway. It’s standard practice and there’s nothing wrong with it, so why cause yourself some potential headaches by omitting keyframes?

  • Pingback: A simple crossfading slideshow made with CSS | Getting Unstuck()

  • http://www.bartensteinpiano.nl/ David Bartenstein

    Thanks Lea! This will save us all some time!

  • Pingback: dev51blog by Joachim Doerr – Animationen mit Keyframes und CSS3()

  • http://www.friv2.org/Flappy_Bird.html flappy bird

    If God wills before she leaves this world she will see what she has done to her once beautiful body and she will regret it

  • Sandeep

    hi … this is a useful trick.. thank you for that .
    I have a question:
    can we delay animation ? if yes , How ?

    • Sandeep

      I mean stop for a while and start again..

  • Jared

    Love this. Thank you.

  • http://www.woopi.com.ar Sebastián

    Hey Lea! I was searching some information about CSS3 scaling objects with scale(). The issue I’ve founded is that when you transform anything with scale(), it gets pixelated in any webkit-based browser. It renders perfect in Firefox, for example. Even with this example you wrote in this post, you can see the heart pixelating when animations occurs. What can we do about it? Is there any method to avoid this problem on a webkit browser? Thanks!!!

  • Pingback: angara fahise()

  • Pingback: kalyan matka()

  • Pingback: http://www.freeformfighters.co.uk/categories/mma-t-shirts/venum-mma-t-shirts.html()

  • Pingback: angara fahise()

  • Pingback: bursa orospu()

  • Pingback: tradeonix - http://www.tradeonixbonuses.com()