Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop infinite CSS3 animation and smoothly revert to initial state

Having some trouble building a CSS3 loader using keyframe animations.

The loader consists of 4 boxes that animate going up and down. The issue I'm having is that when the animation is supposed to stop, the boxes jump to the initial position. The behaviour I'm looking for is: loader is animating infinitely until loading is done, at which point it should animate to the initial position and stop, sort of like having animation-iteration-count: infinite and changing it to animation-iteration-count: 1 to stop the animation. (which doesn't work btw).

See this fiddle to see what I mean: https://jsfiddle.net/cazacuvlad/qjmhm4ma/ (when clicking the stop button, the boxes should animate to the initial position, instead of jumping)

The basic setup is:

<div class="loader-wrapper"><span></span><span></span><span></span><span></span></div>

To start the loader, I'm adding a loader-active class that contains the animation to the loader-wrapper.

LESS:

.loader-wrapper {
  &.loader-active {
    span {
      .animation-name(loader);
      .animation-duration(1200ms);
      .animation-timing-function(ease-in-out);
      .animation-play-state(running);
      .animation-iteration-count(infinite);

      &:nth-child(1) {
      }
      &:nth-child(2) {
        .animation-delay(300ms);
      }
      &:nth-child(3) {
        .animation-delay(600ms);
      }
      &:nth-child(4) {
        .animation-delay(900ms);
      }
    }
  }
}

I've tried adding the animation to the spans in the loader-wrapper class w/o loader-active and playing around with animation-iteration-count and animation-play-state when loader-active is added without any luck.

like image 869
Vlad Cazacu Avatar asked Feb 19 '16 14:02

Vlad Cazacu


1 Answers

Found a pretty simple workaround. Still not pure CSS, it involves a bit of JS, but it works well.

Updated fiddle: https://jsfiddle.net/cazacuvlad/qjmhm4ma/2/

What I did was to move the loader-active class to each span (instead of the wrapper), listen to the animationiteration event on each span and stop the animation then.

$('.loader-wrapper span').on('animationiteration webkitAnimationIteration', function () {
  var $this = $(this);

  $this.removeClass('loader-active');

  $this.off();
});

This basically stops the animation at the very end of an iteration cycle.

Updated LESS

.loader-wrapper {
  span {
    &.loader-active {
      .animation-name(loader);
      .animation-duration(1200ms);
      .animation-timing-function(ease-in-out);
      .animation-play-state(running);
      .animation-iteration-count(infinite);

      &:nth-child(1) {
      }
      &:nth-child(2) {
        .animation-delay(300ms);
      }
      &:nth-child(3) {
        .animation-delay(600ms);
      }
      &:nth-child(4) {
        .animation-delay(900ms);
      }
    }
  }
}
like image 140
Vlad Cazacu Avatar answered Nov 14 '22 22:11

Vlad Cazacu