Continue an infinite CSS animation that gets stopped until its last frame

Viewed 130

I have a defined CSS class spin that creates a simple CSS animation spinner on an element

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.spin {
  animation: spin .8s linear .15s infinite;
}

The spin class is added and removed via JavaScript, however when the class is removed the animation abruptly cuts and the first frame is displayed. Is there are way to have the browser continue to animate the element until it reaches the last frame?

I tired doing multiple combinations of animation-fill-mode, or setting animation-iteration-count: 1 on the "resting" element (i.e., the same element when it does not have the spin class) but nothing worked. Any ideas how to make this work?

1 Answers

If we combine it with the animationiteration event, we can do it.

const spin = document.querySelector(".spin");

let iterationCount = 0;
let isMouseover = 0;

spin.addEventListener('animationiteration', () => {
  iterationCount = 1;
  if (iterationCount && isMouseover) {
    spin.classList.remove("animation");
  } else {
    iterationCount = 0;
  }
});

spin.addEventListener("mouseover", () => {
  isMouseover = 1;
});

spin.addEventListener("mouseout", () => {
  isMouseover = 0;
  spin.classList.add("animation");
});
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.spin {
  height: 100px;
  width: 100px;
  background: yellow;
  border-right: 4px solid green;
  border-left: 4px solid red;
  border-top: 4px solid black;
  border-bottom: 4px solid blue;
}

.spin.animation {
  animation: spin .8s linear .15s infinite;
}
<div class="spin animation"></div>

Works with click also:

const spin = document.querySelector(".spin");

let iterationCount = 0;
let isClicked = 0;

spin.addEventListener('animationiteration', () => {
  iterationCount = 1;
  if (iterationCount && isClicked) {
    spin.classList.remove("animation");
  } else {
    iterationCount = 0;
  }
});

spin.addEventListener("click", () => {
  if (isClicked) {
    isClicked = 0;
    spin.classList.add("animation");
  } else {
    isClicked = 1;
  }
});
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.spin {
  height: 100px;
  width: 100px;
  background: yellow;
  border-right: 4px solid green;
  border-left: 4px solid red;
  border-top: 4px solid black;
  border-bottom: 4px solid blue;
}

.spin.animation {
  animation: spin .8s linear .15s infinite;
}
<div class="spin animation"></div>

Related