Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS animation bug in Safari

I have a CSS animation with a delay and I pause it during the delay. It works as expected on Firefox and Chrome, the "Hello" does not move. However on Safari, the animation jumps to the last frame. Why and how to fix please?

function test() {
  var timeout = 1000;
  setTimeout(function() {
    document.getElementById('animation').style.animationPlayState = 'paused';
  }, timeout);
}

document.addEventListener("DOMContentLoaded", test);
#animation {
  animation: test 2s linear 2s;
}

@keyframes test {
  to {
    transform: translateY(100px);
  }
}
<div id="animation">
  Hello (this text should not move)
</div>

If I remove the 2s delay, set the duration to 4s, and add a keyframe with transform:none, I can make this simple example work. However my real case has multiple animations that are synchronized with delays.

like image 234
Patrick Avatar asked Oct 10 '17 14:10

Patrick


People also ask

Does Safari support CSS animation?

Safari supports two types of CSS animation: transition animations and keyframe animations.

Why is my CSS animation not working?

Animation Duration Not Set By default, a CSS animation cycle is zero seconds long. To override this, add an animation-duration rule to your targeted element with a seconds value, in the same block as animation-name. Below, try removing the comments around animation-duration to fix the animation.

Do CSS animations work on all browsers?

CSS Animation element is supported by all Microsoft Edge browser.


2 Answers

The Safari behaviour is only buggy when timeout is set to a value smaller than the animation delay. So, a workaround is to set the initial state to paused via animation-play-state and then control it via JS, as shown below:

function test() {
  let el = document.getElementById("animation");
  let timeout = 1000;
  
  // Get the delay. No luck with el.style.animationDelay
  let delay =
    window
      .getComputedStyle(el)
      .getPropertyValue("animation-delay")
      .slice(0, -1) * 1000;

  // Only resume and later pause when timeout is greater than animation delay
  if (timeout > delay) {
    el.style.animationPlayState = "running";
    setTimeout(function() {
      el.style.animationPlayState = "paused";
    }, timeout);
  }
}

document.addEventListener("DOMContentLoaded", test);
#animation {
  animation: test 2s linear 3s;
  animation-play-state: paused; /* Pause it right after you set it */
}

@keyframes test {
  to {
    transform: translateY(100px);
  }
}
<div id="animation">
  Hello (this text should not move)
</div>

Try different timeout values to see it working. Can't say why this is happening though. Looks like a bug to me. Tested on OS X El Capitan 10.11.6 / Safari 11.0 (11604.1.38.1.7).

Codepen demo

like image 84
Kostas Siabanis Avatar answered Oct 17 '22 09:10

Kostas Siabanis


This is not an answer to the problem. However, if you remove the animation delay, pausing and restarting the animation works as it should. It seems then the animation delay is what is causing the problem. Perhaps rather than relying on css to handle the delay, programmatically control animation delay with javascript.

See below pausing and running the animation

function test() {
  var timeout = 1000;
  setTimeout(function() {
    document.getElementById('animation').style.animationPlayState ='paused';
    document.getElementById('animation').style.webkitAnimationPlayState ='paused';
  }, timeout);
  setTimeout(function() {
    document.getElementById('animation').style.animationPlayState='running';
    document.getElementById('animation').style.webkitAnimationPlayState ='running';
  }, timeout * 2);
}

document.addEventListener("DOMContentLoaded", test);
#animation {
    -webkit-animation: test 2s linear;
        animation: test 2s linear;
}

@-webkit-keyframes test {
  to {
    -webkit-transform: translateY(100px);
        transform: translateY(100px);
  }
}

@keyframes test {
  to {
    -webkit-transform: translateY(100px);
        transform: translateY(100px);
  }
}
<div id="animation">
  Hello (this text should not move)
</div>
like image 23
wlh Avatar answered Oct 17 '22 09:10

wlh