How to slow down the last few frames in a CSS sprite animation?


Tags: css,css3,css-animations,css-sprites

Problem :

I have a CSS sprite animation.

I would like the animation to slow down, before it stops.
enter image description here

I have a total of 10 Frames.
Frame 1-5 should be 0.8s, Frame 6-7 should be 2s and Frame 8-10 should be 3s.

.hi3 {
  width: 73px;
  height: 75px;
  background-image: url("../img/dice3.fw.png");

  -webkit-animation: play .8s steps(10) forwards;
     -moz-animation: play .8s steps(10) infinite;
      -ms-animation: play .8s steps(10) infinite;
       -o-animation: play .8s steps(10) infinite;
          animation: play .8s steps(10) forwards;   
}

@-webkit-keyframes play {
   from { background-position:    0px; }
   to { background-position: -722px; }
}

@keyframes play {
  from { background-position:    0px; }
  to { background-position: -722px; }
}

Is it possible to do this all in CSS? This animation is being used in a hybrid IONIC app.



Solution :

I have a total of 10 Frames. Frame 1-5 should be 0.8s, Frame 6-7 should be 2s and Frame 8-10 should be 3s. Is it possible to do this all in CSS?

Yes, it is possible but for that the animation-timing-function needs to be modified and @keyframes should be coded accordingly. The steps function divides frames into equidistant steps based on the no. of steps that is provided as parameter and jumps from one step to another.

The below is what MDN has to say about this timing-function:

The steps() functional notation defines a step function dividing the domain of output values in equidistant steps.

Because of the above, the steps() function cannot be used to create the effect that you are looking for (as each step is equidistant and so has equal timing).


Solution:

The following are the things that need to be done in-order to get the output that you're looking for:

  • Calculate the total animation-duration based on your expectation. My interpretation is that you need .8s for each of the first 5 frames (4s), 2s for the next two (4s) and 3s for the next three (9s) and so the total animation-duration should be set as 17s. (Note: Alternately, if you mean that all the first 5 frames should be completed within 0.8s and so on, then duration will be 5.8s).
  • Change the animation-timing-function to linear because the steps() function will not work as mentioned above.
  • Calculate the splits for @keyframes based on the no. of seconds for each frame and animation's total duration. Formula would be (No. of seconds for the frame / Total Duration * 100) and so the first 5 frames would roughly need to be present for 4.70% of the animation, the next 2 for 11.76% and the last 3 for 17.64%. (Note: Splits would change if you were looking for 5.8s duration).
  • Now based on the splits, write the @keyframes selectors (the percentage values). The key thing to note while writing the keyframe selectors is that a sprite animation should typically jump from one frame to another (not a linear slide movement) and so, each frame should be shown until the time when the next frame has to be shown. For example, frame 2 has to be shown at 4.70% and so the frame 1's background-position should be maintained from 0% to 4.69%.

Demo with 17s duration: (each of the first 5 frames get 0.8s, each of the next 2 get 2s and each of the last 3 get 3s)

.hi {
  width: 50px;
  height: 72px;
  background-image: url("http://s.cdpn.io/79/sprite-steps.png");
  animation: play 17s linear infinite;
}
@keyframes play {
  0%, 4.69% {     /* 0.8s */
    background-position: 0px;
  }
  4.70%, 9.39% {  /* 0.8s */
    background-position: -50px;
  }
  9.40%, 14.09% { /* 0.8s */
    background-position: -100px;
  }
  14.10%, 18.79% { /* 0.8s */
    background-position: -150px;
  }
  18.80%, 23.49% { /* 0.8s */
    background-position: -200px;
  }
  23.5%, 35.25% {  /* 2s */
    background-position: -250px;
  }
  35.26%, 47.01% { /* 2s */
    background-position: -300px;
  }
  47.02%, 64.65% { /* 3s */
    background-position: -350px;
  }
  64.66%, 82.29% { /* 3s */
    background-position: -400px;
  }
  82.3%, 100% { /* 3s */
    background-position: -450px;
  }
}
<img src="http://s.cdpn.io/79/sprite-steps.png" />
<div class="hi"></div>

Demo with 5.8s duration: (the first 5 frames get 0.8s in total, the next 2 get 2s in total and final 3 get 3s in total)

.hi {
  width: 50px;
  height: 72px;
  background-image: url("http://s.cdpn.io/79/sprite-steps.png");
  animation: play 5.8s linear infinite;
}
@keyframes play {
  0%, 2.74% {     /* 0.16s */
    background-position: 0px;
  }
  2.75%, 5.49% {  /* 0.16s */
    background-position: -50px;
  }
  5.50%, 8.24% { /* 0.16s */
    background-position: -100px;
  }
  8.25%, 10.99% { /* 0.16s */
    background-position: -150px;
  }
  11.00%, 13.74% { /* 0.16s */
    background-position: -200px;
  }
  13.75%, 30.99% {  /* 1s */
    background-position: -250px;
  }
  31.00%, 48.24% { /* 1s */
    background-position: -300px;
  }
  48.25%, 65.49% { /* 1s */
    background-position: -350px;
  }
  65.50%, 82.74% { /* 1s */
    background-position: -400px;
  }
  82.75%, 100% { /* 3s */
    background-position: -450px;
  }
}
<img src="http://s.cdpn.io/79/sprite-steps.png" />
<div class="hi"></div>

Disclaimer: The sprite image is not my own and it was adapted from this fiddle found through Google search.


    CSS Howto..

    How can i get target with a hover an element under an element?

    How to implement this kind of blur effect?

    How to use Aural CSS?

    how to really include html codes inside php

    How to slow drop menu animation with CSS only

    How should I handle this CSS Inheritance conundrum?

    How can I properly display my divs in masonry style using flex?

    On Eclipse-Java EE, how do I change the color settings for selected elements on a tree view?

    Primefaces p:growl css. How to extend div message background color width

    css - how to remove inherited style

    Menu hover effect - how to reproduce this effect?

    How do I load / unload css changes quickly on a plone + Zope site ? (noob)

    CSS classes: base+additional. How to define?

    how to resize images inside a div inside another div with css?

    CSS - how to set a position of UL in LI

    jQuery slideshow with separate div containing image specific text

    How to automatically scroll when div expands at bottom of page?

    How should I use `position` and other properties correctly to position my web page?

    Why does an absolutely positioned child expand container height and how to prevent this?

    How to add / remove html elements and content based on the browsing device?

    How to keep indent in lists with CSS?

    How to make input placeholder text not opaque when the text field background is opaque

    How to build a mobile version of a non-mobile website? [closed]

    How to position two divs on either side of the screen, HTML, CSS

    How to add text using css in textarea? [closed]

    How to edit CSS styles in JavaScript?

    How can I apply a CSS class to an element with a given id, without modifying the element?

    How do i hook media queries to screen resolution?

    How to make CSS triangles (with borders) compatible across browsers

    How to change CSS element of data-pid using jquery