Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can `animation-play-state` in CSS be initially set to `paused` and changed to `running`?

Using CSS and HTML, a checkbox, an index and a content div were created. The index has a fixed position and is floated floated at the left. The content adjusts its width to the available space and thus takes its place next to index. The checkbox toggles between two states: :not(:checked) moves the index and content to the right. :checked moves the index and content to the left, pushing index off-screen.

These moves are CSS3 animations: moveindexleft, movecontentleft, moveindexright and movecontentright. index and content have their animation-play-state initially set at paused. Ticking the checkbox changes that to running. This is to prevent the animation being played right after the initial loading of the page.

Testing in Firefox 42.0 and Chromium 47.0.2526.80 (64-bit), the issue is that this initial animation-play-state: paused is ignored.

The result: https://jsfiddle.net/Lmzyxzhs/

How can animation-play-state in CSS be initially set to paused and changed to running?

N.b.: If initially set to animation-play-state: paused !important;, then the checkbox toggle does not override this, disabling all animations.

Additionally, there seems to be a slight delay after clicking on the checkbox and initiating the animation. Can this be optimized?

like image 834
rayanamukami Avatar asked Dec 17 '15 21:12

rayanamukami


People also ask

What is animation play state in CSS?

CSS animation-play-state property specifies if the animation is running or it is paused. If you resume a paused animation it will start from where it was left off at the time it was paused, rather than starting from the beginning of the animation sequence.

How to pause an animation in CSS?

The only way to truly pause an animation in CSS is to use the animation-play-state property with a paused value. In JavaScript, the property is “camelCased” as animationPlayState and set like this: We can create a toggle that plays and pauses the animation by reading the current value of animationPlayState:

How do I know if an animation is running or paused?

The animation-play-state CSS property sets whether an animation is running or paused. Resuming a paused animation will start the animation from where it left off at the time it was paused, rather than starting over from the beginning of the animation sequence. The animation is currently playing. The animation is currently paused.

What is the animation-play-state property used for?

The animation-play-state property is used to specify whether an animation is running or paused. Animations in CSS allow you to change the state of an element.


1 Answers

There is no problem with the animation-play-state property and none of the browsers ignore it. The problem that you are facing is because of the selectors and the way they work. The :not(:checked) selector would match the original/default state of your checkbox also because, well, it is not selected. This combined with the fact that that the :not(:checked) selector appears later in your CSS file and that it has more specificity than div#index or div#content selector makes the animation play state setting defined within this :not(:checked) selector (which is running) take precedence. This is the reason why the animation is getting executed on page load also.

As far as I am aware you cannot achieve both (a) pause the animation on load and (b) have a reverse animation when the checkbox is not checked using CSS selectors alone. At any given point, you can get only one of those to work.

Hence, the recommended solution for you would be to use JavaScript (or any preferred libraries) and add a class to the element the very first time the user clicks on the checkbox. Then the :checked or :not(:checked) styling can be applied only when the checkbox has this extra class.

var chkBox = document.getElementById('toggle');

chkBox.addEventListener('click', function(){
  this.classList.add('user-interacted');
});
div#index {
  position: fixed;
  float: left;
  width: 10em;
  left: 0em;
  animation-fill-mode: both;
  animation-play-state: paused;
  animation-duration: 1s;
}
div#content {
  width: auto;
  margin-left: 10em;
  animation-fill-mode: both;
  animation-play-state: paused;
  animation-duration: 1s;
}
@keyframes moveindexleft {
  0% {
    left: 0em;
  }
  100% {
    left: -10em;
  }
}
@keyframes movecontentleft {
  0% {
    margin-left: 10em;
  }
  100% {
    margin-left: 0em;
  }
}
@keyframes moveindexright {
  0% {
    left: -10em;
  }
  100% {
    left: 0em;
  }
}
@keyframes movecontentright {
  0% {
    margin-left: 0em;
  }
  100% {
    margin-left: 10em;
  }
}
input[type=checkbox] {
  display: none;
}

/* note the change in selectors */
input[type=checkbox].user-interacted:not(:checked) ~ div#index {
  animation-play-state: running;
  animation-name: moveindexright;
}
input[type=checkbox].user-interacted:not(:checked) ~ div#content {
  animation-play-state: running;
  animation-name: movecontentright;
}
input[type=checkbox].user-interacted:checked ~ div#index {
  animation-play-state: running;
  animation-name: moveindexleft;
}
input[type=checkbox].user-interacted:checked ~ div#content {
  animation-play-state: running;
  animation-name: movecontentleft;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<label for="toggle">
  Button
</label>

<input id="toggle" type=checkbox>
<div id="index">
  index
</div>

<div id="content">
  content
</div>

Alternately, you can achieve the same effect by just using CSS transition (as pointed out by vals in his comment). Transitions get triggered only when user clicks on the checkbox (unlike animation which starts automatically on page load). Below is a sample snippet for this approach.

div#index {
  position: fixed;
  float: left;
  width: 10em;
  left: 0em;
  transition: left 1s linear;
}
div#content {
  width: auto;
  margin-left: 10em;
  transition: margin-left 1s linear;
}
input[type=checkbox] {
  display: none;
}
input[type=checkbox]:not(:checked) ~ div#index {
  left: 0em;
}
input[type=checkbox]:not(:checked) ~ div#content {
  margin-left: 10em;
}
input[type=checkbox]:checked ~ div#index {
  left: -10em;
}
input[type=checkbox]:checked ~ div#content {
  margin-left: 0em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<label for="toggle">
  Button
</label>

<input id="toggle" type=checkbox>
<div id="index">
  index
</div>

<div id="content">
  content
</div>
like image 88
Harry Avatar answered Sep 27 '22 16:09

Harry