Why does CSS animation have no duration?

I have several animations that need to transition from one state to another. The transition from state empty

to state bit

works great, which means from bit

to large

, but when I try to use the reverse animation that I add as classes, the animations have no duration. Here is 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 animation.

+3


source to share


1 answer


Animation has a duration. The problem is that the animation is already finished, and changing the class will not play the animation from the beginning unless the animation name property changed. So one way to solve this problem would be to create separate animations for the classes bit-empty

and large-bit

:

.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>
      

Run codeHide result


View JSFiddle



The best solution, though, would be to not use animation at all. In my opinion, transitions are a much better tool to work with 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>
      

Run codeHide result


View JSFiddle

+2


source







All Articles