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
1 Like

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

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