Luca Rossi
Luca Rossi

Reputation: 409

How to restart CSS Animation with minimal impact

Is there a way to restart a CSS animation without cloning elements, reflowing DOM, waiting (setTimeout/onAnimationEnd)?

Upvotes: 5

Views: 7392

Answers (2)

Prid
Prid

Reputation: 1624

The simplest and most reliable way to "restart" CSS animations I've found is this answer: https://stackoverflow.com/a/72525340/3705191

TL;DR: switch between two identical keyframe animations


Here's the gist of it:

  1. Create 2 identical keyframe declarations (e.g. animation1 and animation2)
  2. Assign one of them to your desired element's animation property
  3. When wanting to restart, check the name of the animation keyframes the element currently has, and then switch over to the other keyframes name
    • this can be achieved in various ways, but it's the switching that's essential

Example

@keyframes popup1 {
  0% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes popup2 {
  0% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1);
  }
}
.animated-element {
  animation: popup1 200ms ease;
}
// when wanting to restart:
const el = document.$('.animated-element');

// animationName only returns the name
if( el.style.animationName == 'popup1' ){
  el.style.animation = 'popup2 200ms ease';
} else {
  el.style.animation = 'popup1 200ms ease';
}

Upvotes: 1

Luca Rossi
Luca Rossi

Reputation: 409

EDIT: No jQuery or check needed.

I basically just restart the animation at the next painted frame.

This method doesn't clone any element, reflows the document, setting any timeout, or waiting for completion of the animation. It is 100% flexible and requires no jQuery.

I haven't seen anything similar (not even at css-tricks) so I wanted to share my idea with you and hear your thoughts.

Browser support

document.querySelector('.box').onclick = function(){
  requestAnimation( this );
};

var requestAnimation = function( obj ){
  obj.style.animation = 'none';
  window.requestAnimationFrame(function(){
    obj.style.animation = 'myAnimation 1s';
  });
}
html{ background: #212121; }

.box{
  width: 150px;
  background: white;
  cursor: pointer;
  text-align: center;
  margin: auto;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 0 3px black;
}
span{
  float: right;
  color: grey;
}
@keyframes myAnimation{
  from{ background: grey; transform: scale(1.2); }
  to{ background: white; transform: scale(1); }
}
<div class="box">I can animate forever!</div>
<span>By Luca Rossi</span>

Upvotes: 11

Related Questions