Restarting a CSS Animation

Learn how to restart a CSS animation in a way that works across all modern mobile and desktop browsers!


This is a companion discussion topic for the original entry at https://www.kirupa.com/animations/restarting_css_animations.htm
2 Likes

I’m viewing this in Firefox and the example doesn’t work. Clicking restart does nothing.

1 Like

What version of Firefox on what OS?

My FF is up to date at version 98.0.1 (64-bit) and it’s running on Windows 10

It works for me on macOS, so there must be some rendering quirks between platforms that is causing this. Let me spin up a Windows VM shortly and see what is going on and/or whether an alternate solution needs to be explored here. Sorry about that. I usually only double and triple check with Safari, for that is the browser that happens to have the most quirks. Chrome and Firefox always just work! :train:

Any luck?

Yes, actually! I think. Can you try this:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Restart Animation</title>
<style>
    body {
      display: grid;
      place-items: center;
    }

    .circle {
      width: 100px;
      height: 100px;
      background-color: #D72638;
      border-radius: 50%;

      animation-name: scaleUp;
      animation-iteration-count: 1;
      animation-duration: 1s;
      animation-fill-mode: both;
      animation-timing-function: cubic-bezier(.17, .67, .32, 1.55)
    }

    @keyframes scaleUp {
      0% {
        transform: scale(3, 3);
      }

      50% {
        transform: scale(-.5, -.5);
      }

      100% {
        transform: scale(3, 3);
      }
    }

    .container {
      width: 500px;
      height: 500px;
      box-shadow: 0px 10px 20px #666;
      overflow: hidden;
      display: grid;
      place-items: center;
      background-color: #FFFD98;
      border-radius: 10px;
      align-items: end;
    }

    #restartButton {
      margin-bottom: 40px;
      padding: 5px;
      font-weight: bold;
      border: none;
      outline: 2px solid #0880ff;
      border-radius: 5px;
      background-color: #FFF;
    }

    #restartButton:hover {
      outline-width: 5px;
      background-color: #EAF4FF;
    }
  </style>
</head>
<body>
<div class="container">
<div class="circle"></div>
<button id="restartButton">Restart</button>
</div>
<script>
    let restartButton = document.querySelector("#restartButton");
    restartButton.addEventListener("click", restartAnimation, false);

    function restartAnimation() {
      let circle = document.querySelector(".circle");

      circle.style.animationName = "none";

      requestAnimationFrame(() => {
        setTimeout(() => {
          circle.style.animationName = ""
        }, 0);
      });
    }
  </script>
</body>
</html>

This adds a setTimeout to the requestAnimationFrame call. A live version of it is here: Restart Animation

Let me know if this works @mistafisha! I’ll update the code and add a note to the video about this.

Cheers,
Kirupa

Yes, that worked. It seems very strange though since the timeout is for 0 seconds! Can you explain why this work?

I don’t know :stuck_out_tongue:

These are parts of the large undocumented behaviors all browsers have in terms of when they validate and invalidate styles. My guess is that a setTimeout triggers some code path that forces an invalidation in Firefox whereas a regular requestAnimationFrame by itself doesn’t.

I’m hoping this continues to work. I’ll try to carve up some time and file a bug in Firefox’s database giving their developers a heads-up that this behavior now works but didn’t work when setTimeout is removed.

1 Like

LOL. Well I’m glad I could contribute my bug so you could incorporate it into your instructions! And maybe even get Firefox themselves to address it!

1 Like