Spinning a coin

I’ve made the following pen to spin a coin, just because I could. I would like to be able to (a) add animation-timing-function in the options and (b) wait for the animation to finish so I can do something else. Is either possible?

Don’t know what exactly you mean with animation timing function, but of course you can setup a callback function for the options instead of the static object.

To get the animation end you need to add another event listener and wait for “animationend”


Is the something else another animation? If so then the whole thing wold be easier in css. Just use JS to add a class to start the animation.

However I guess you are just practicing the JS so I’ll keep my mouth shut :slight_smile:

1 Like

Add the easing option.

Use the finished promise.


It would look better if the other side of the coin is shown between 90° and 270° rotation.

There’s a challenge :smiley:.


Here’s how,

const coin = document.getElementById("coin");

coin.addEventListener("click", function () {
  const keyframes = [
    { transform: "rotateX(0deg)" },
    { transform: "rotateX(360deg)" }
  const options = {
    duration: 1000,
    iterations: 6,
    easing: "ease-in-out" 

  const animation = coin.animate(keyframes, options);

  animation.onfinish = function() {
    // Do something else here

1 Like

Thanks. I was getting my proverbials in a twist with the callback function.

Indeed. I think that’s above my pay grade! :lol: Even finding a “heads” and a “tails” side for the same coin is a challenge…

I started off using CSS but once the animation was complete it wasn’t repeatable.


Nah, the idea was not to spin the coin for ever, but for 6 or whatever times, then be able to spin it again.

CSS your animation on a class (.spin)
Bind your button to do this:

//Assume: element = the image.
//Clean up any previous run...
void element.offsetLeft; 
//This forces a reevaluation of the element by the browser, to recognize the class has been removed.
//Adding the class should force the animation to play again.

Here’s a simple example with your 2 different images.

It’s not real 3d as you’d also need images for the edges to do that.


Oh cool! Many thanks, squire.

1 Like

Thanks everyone for your help. Here is the finished article :shifty:

https:// gandalf458 .co.uk/weather/


That’s pretty accurate :slight_smile:

1 Like

“Telling the weather in the UK is easy. Look to the hill to the west; if you can see the top, its going to rain. If you cant, it is raining.”


Interested in how you would approach that. I remember doing a giff animation of a spinning coin for someone back in 1999.

Also a couple of years ago on here I did a spinning logo using sprites, which was driven by scrolling the page.

I’m sure it could be refactored, but I am also wondering if there are better ways of doing this now. three.js perhaps?



For continuous spinning you don’t need JavaScript . . . .

1 Like

I’d fake it like this:

You just stack a number of the same images on top of each other and then rotate them with a slight offset to give the edge.

You can even do the scroll effect without js these days (in modern browsers).


IIRC @alexwalker did a rotating 3D object some years ago - a rotating book showing the spine. Can’t find it though.

Edit: I have found it! Pure CSS 3D product shots from a 2D graphic


Animation a cube is a littler easier than animating a real 3d object but I imagine if you replaced the panels with background images of the real object you would get a reasonable facsimile.

I did an animated dice 10 years ago which makes it easier to see the panels being used.

(Hover the dice to start the animation)

Bear in mind this was using prefixes as it was an early implementation. I never got around to updating it :slight_smile:

As you are using a sprite with only a set number of images then there’s always going to be a bit of a jump. I think it would look smoother using the two image method in my last coin example and stacking the same image to get depth.

I did have a quick look at animating your sprite in CSS in a similar way to your js only but it didn’t look good as I seem to have missed some frames out. I’ll have to have a look at it when I have more time :slight_smile:

As proof of concept its ok but I don’t think i’ve matched the frames up properly and I probably should have used the steps() value for both .:wink: