Reputation: 2662
I have a few animations that should go from one state to the other. Going from state empty
to state bit
works fine and so does from bit
to large
, but when I try to use the reverse animations which I add as classes, the animations have no duration. Here's a snippet of my code:
@keyframes empty-bit {
0% {width: 0%;}
100% {width: 4px;}
}
@keyframes bit-large {
0% {width: 4px;}
100% {width: 100%;}
}
.timeline-empty-bit {
animation-name: empty-bit;
animation-fill-mode: forwards;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-delay: 200ms;
}
.timeline-bit-large {
animation-name: bit-large;
animation-fill-mode: forwards;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
}
.timeline-large-bit {
animation-name: bit-large;
animation-fill-mode: forwards;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-direction: reverse;
animation-delay: 200ms;
}
.timeline-bit-empty {
animation-name: empty-bit;
animation-fill-mode: forwards;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-direction: reverse;
}
Here's a jsfiddle: https://jsfiddle.net/9tmm46fz/ Use arrows (left, right) to see the animation.
Upvotes: 3
Views: 203
Reputation: 48378
The animation does have a duration. The problem is the animation already finished playing, and changing the class won't play the animation from the beginning unless the animation-name property changes. So one way to solve this would be to create separate animations for the bit-empty
and large-bit
classes:
.timeline-gauge {
height: 20px;
}
.timeline-gauge-container {
display: inline-block;
height: 100%;
}
.timeline-gauge-part {
display: block;
height: 100%;
width: 0%;
}
@keyframes empty-bit {
0% {width: 0%;}
100% {width: 4px;}
}
@keyframes bit-empty {
0% {width: 0%;}
100% {width: 4px;}
}
@keyframes bit-large {
0% {width: 4px;}
100% {width: 100%;}
}
@keyframes large-bit {
0% {width: 4px;}
100% {width: 100%;}
}
.timeline-empty-bit {
animation-name: empty-bit;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-delay: 200ms;
}
.timeline-bit-large {
animation-name: bit-large;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
}
.timeline-large-bit {
animation-name: large-bit;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-direction: reverse;
animation-delay: 200ms;
}
.timeline-bit-empty {
animation-name: bit-empty;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-direction: reverse;
}
var containers = document.getElementsByClassName("timeline-gauge-container");
var length = containers.length;
for (var i = 0; i < length; i++) {
containers[i].style.width = containers[i].getAttribute("percentage");
}
var parts = document.getElementsByClassName("timeline-gauge-part");
var length = parts.length;
for (var i = 0; i < length; i++) {
parts[i].style.backgroundColor = parts[i].getAttribute("color");
}
var index = 0;
parts[0].classList.add("timeline-empty-bit");
function removeAnimation(part) {
part.classList.remove("timeline-empty-bit");
part.classList.remove("timeline-bit-large");
part.classList.remove("timeline-large-bit");
part.classList.remove("timeline-bit-empty");
}
document.onkeydown = function(event) {
if (event.keyCode == 37 && index > 0) {
removeAnimation(parts[index - 1]);
parts[index - 1].classList.add("timeline-large-bit");
if (index != length) {
removeAnimation(parts[index]);
parts[index].classList.add("timeline-bit-empty");
}
index--;
}
if (event.keyCode == 39 && index < length) {
removeAnimation(parts[index]);
parts[index].classList.add("timeline-bit-large");
if (index != length - 1) {
removeAnimation(parts[index + 1]);
parts[index + 1].classList.add("timeline-empty-bit");
}
index++;
}
};
.timeline-gauge {
height: 20px;
}
.timeline-gauge-container {
display: inline-block;
height: 100%;
}
.timeline-gauge-part {
display: block;
height: 100%;
width: 0%;
}
@keyframes empty-bit {
0% {width: 0%;}
100% {width: 4px;}
}
@keyframes bit-empty {
0% {width: 0%;}
100% {width: 4px;}
}
@keyframes bit-large {
0% {width: 4px;}
100% {width: 100%;}
}
@keyframes large-bit {
0% {width: 4px;}
100% {width: 100%;}
}
.timeline-empty-bit {
animation-name: empty-bit;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-delay: 200ms;
}
.timeline-bit-large {
animation-name: bit-large;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
}
.timeline-large-bit {
animation-name: large-bit;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-direction: reverse;
animation-delay: 200ms;
}
.timeline-bit-empty {
animation-name: bit-empty;
animation-fill-mode: both;
animation-duration: 200ms;
animation-timing-function: ease-in-out;
animation-direction: reverse;
}
<div class="timeline-container">
<div class="timeline-gauge">
<div class="timeline-gauge-container" percentage="5%"><span class="timeline-gauge-part" color="#4f5f6b"></span></div><div class="timeline-gauge-container" percentage="20%"><span class="timeline-gauge-part" color="#237487"></span></div><div class="timeline-gauge-container" percentage="10%"><span class="timeline-gauge-part" color="#00b188"></span></div><div class="timeline-gauge-container" percentage="20%"><span class="timeline-gauge-part" color="#008e6c"></span></div><div class="timeline-gauge-container" percentage="25%"><span class="timeline-gauge-part" color="#99ca34"></span></div><div class="timeline-gauge-container" percentage="20%"><span class="timeline-gauge-part" color="#9059a2"></span></div>
</div>
</div>
A better solution though would be to not use animations at all. In my opinion, transitions are a much better tool for the job in this case:
.timeline-gauge {
height: 20px;
}
.timeline-gauge-container {
display: inline-block;
height: 100%;
}
.timeline-gauge-part {
display: block;
height: 100%;
width: 0%;
transition: width 200ms ease-in-out;
}
.timeline-empty-bit {
width: 4px;
transition-delay: 200ms;
}
.timeline-bit-large {
width: 100%;
}
.timeline-large-bit {
width: 4px;
transition-delay: 200ms;
}
.timeline-bit-empty {
width: 0%;
}
var containers = document.getElementsByClassName("timeline-gauge-container");
var length = containers.length;
for (var i = 0; i < length; i++) {
containers[i].style.width = containers[i].getAttribute("percentage");
}
var parts = document.getElementsByClassName("timeline-gauge-part");
var length = parts.length;
for (var i = 0; i < length; i++) {
parts[i].style.backgroundColor = parts[i].getAttribute("color");
}
var index = 0;
parts[0].classList.add("timeline-empty-bit");
function removeAnimation(part) {
part.classList.remove("timeline-empty-bit");
part.classList.remove("timeline-bit-large");
part.classList.remove("timeline-large-bit");
part.classList.remove("timeline-bit-empty");
}
document.onkeydown = function(event) {
if (event.keyCode == 37 && index > 0) {
removeAnimation(parts[index - 1]);
parts[index - 1].classList.add("timeline-large-bit");
if (index != length) {
removeAnimation(parts[index]);
parts[index].classList.add("timeline-bit-empty");
}
index--;
}
if (event.keyCode == 39 && index < length) {
removeAnimation(parts[index]);
parts[index].classList.add("timeline-bit-large");
if (index != length - 1) {
removeAnimation(parts[index + 1]);
parts[index + 1].classList.add("timeline-empty-bit");
}
index++;
}
};
.timeline-gauge {
height: 20px;
}
.timeline-gauge-container {
display: inline-block;
height: 100%;
}
.timeline-gauge-part {
display: block;
height: 100%;
width: 0%;
transition: width 200ms ease-in-out;
}
.timeline-empty-bit {
width: 4px;
transition-delay: 200ms;
}
.timeline-bit-large {
width: 100%;
}
.timeline-large-bit {
width: 4px;
transition-delay: 200ms;
}
.timeline-bit-empty {
width: 0%;
}
<div class="timeline-container">
<div class="timeline-gauge">
<div class="timeline-gauge-container" percentage="5%"><span class="timeline-gauge-part" color="#4f5f6b"></span></div><div class="timeline-gauge-container" percentage="20%"><span class="timeline-gauge-part" color="#237487"></span></div><div class="timeline-gauge-container" percentage="10%"><span class="timeline-gauge-part" color="#00b188"></span></div><div class="timeline-gauge-container" percentage="20%"><span class="timeline-gauge-part" color="#008e6c"></span></div><div class="timeline-gauge-container" percentage="25%"><span class="timeline-gauge-part" color="#99ca34"></span></div><div class="timeline-gauge-container" percentage="20%"><span class="timeline-gauge-part" color="#9059a2"></span></div>
</div>
</div>
Upvotes: 2