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. 😉

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

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

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

        • And that wasn’t even intentional, LOL!

  • 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!

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

  • pretty awesome. thanks Lea!

  • Fantastic

  • 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.

  • criography

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

  • Good one!! Thanks.

  • Guest

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

  • 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()

  • 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.

  • 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.

    • 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 🙁

        • 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()

  • 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?

    • 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!

  • 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/

    • 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()

  • Thanks Lea! This will save us all some time!

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

  • 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.

  • 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()

  • Gato

    buena he, me sirvio

  • John Smith

    Lea, you are one of the few people who could figure this out! I’ve seen
    your other work, and you have serious coding skills. Trust me, I have
    TRIED other coding forums and all I got was insulted.

    Can you take a quick look, please?

    Navigate to this page: https://www.pinterest.com/pin/503840277038080224/
    You will need to log in (anything will work) to go to the actual page.

    Over the “SAVE” button, you will see a blue “TwoCirclesPulser” when you
    inspect the element in Firebug. You will also see the CSS classes
    changing every second, the timing and the opacity. This is done by a
    script that adds and removes classes from the element.

    The pinterest scripts are HUGE, like 10,000 lines of code. I have not been
    able to remove just the script that animates the pulser. It looks like
    they append to the element, and use some sort of event listener, from
    what I can see in the debugger.

    Can you show me how to do this, using javascript or the Jquery framework?

    Anyone can use static animation. This particular example is using scripting to change the CSS classes, on a time basis.

    Obviously, I do not have the scripting skills to do this myself. Not yet, anyway!

  • Pingback: boldenone()

  • Pingback: discount stanozolol()

  • Pingback: testosterone enanthate uk()

  • Pingback: dimagrire senza dieta()

  • Pingback: xmt85c4wx5ctwxw3tcerthve56()

  • Davis Hulen

    When it comes to learning animation, it is ideal and effective thing to learn how to use proper applications of the key-frame because this is the one who control the movement of animated pictures.