Timing for opacity keyframe animation

Viewed 87

I'm trying to animate the opacity on some simple Font Awesome icons, but I can't get the timing right.

Basically, of the 5 circles, I want the last 3 on either end to animate on together. So, when the far-left 3 are on, the remaining far-right 2 are off and vice versa. I sort of have this happening on the last 2 on either end, but it's not very smooth and I haven't accounted for the middle one yet. I'm reversing the animation on either end, but I'm not sure if I should just create separate keyframes.

Desired pattern: https://youtu.be/zPPhFs1Y4Ts?t=89

@keyframes blinker-skip {
  0% {
    opacity: 0;
  }
  10% {
    opacity: 0;
  }
  20% {
    opacity: 0;
  }
  30% {
    opacity: 0;
  }
  40% {
    opacity: 0;
  }
  50% {
    opacity: 0;
  }
  60% {
    opacity: 0;
  }
  70% {
    opacity: 1;
  }
  80% {
    opacity: 0;
  }
  90% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

.boosted-led-blink-skip-first {
  animation: blinker-skip 1s linear infinite;
}

.boosted-led-blink-skip-second {
  animation: blinker-skip 1s linear reverse infinite;
}

.boosted-led-blink-middle {
  animation: blinker 1s step-start infinite;
}

.boosted-led-orange {
  color: #ff8533;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css">
<div class="boosted-leds">
  <span class="boosted-led-orange boosted-led-blink-skip-first boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-skip-first boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-middle boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-skip-second boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-skip-second boosted-led"><i class="fas fa-circle"></i></span>
</div>

Demo: https://codepen.io/ourcore/pen/GRZYjxZ

2 Answers

It looks like you want the dots to show for 50% of the time on one side and then 50% of the time of the other side.

You can do this by having the opacity at 0 from 0-49% and then set it to 1 for 50-100%. You already use reverse for the second set so that will (obviously!) run the opposite way for set 2.

Working example:

.boosted-led-orange {
  color: #ff8533;
}

@keyframes blinker-skip {
  0% {
    opacity: 0;
  }
  49% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 1;
  }
}

.boosted-led-blink-skip-first {
    animation: blinker-skip 1s linear infinite;
  }

.boosted-led-blink-skip-second {
    animation: blinker-skip 1s linear reverse infinite;
  }

.boosted-led-blink-middle {
    animation: blinker 1s step-start infinite;
  }
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css">

<div class="boosted-leds">
  <span class="boosted-led-orange boosted-led-blink-skip-first boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-skip-first boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-middle boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-skip-second boosted-led"><i class="fas fa-circle"></i></span>
  <span class="boosted-led-orange boosted-led-blink-skip-second boosted-led"><i class="fas fa-circle"></i></span>
</div>

Note that you only need to include the keyframes for the times where the changes occur - there is no need to include the ones in between.

If you are intrested you can do this with one element and without font awesome

.loading {
  width:200px;
  margin:5px;
  background:linear-gradient(#ff8533 0 0) left/60% 100% no-repeat;
  -webkit-mask:radial-gradient(circle closest-side, #fff 97%,transparent 100%) 0/calc(100%/5) 100%; 
  animation: blinker-skip 1s linear infinite;
}
.loading::before {
  content:"";
  display:block;
  padding-top:calc(100%/5 - 5px); /* 5px is the space between circles */
}

@keyframes blinker-skip {
  0%,49% {
    background-position: left;
  }
  50%,100% {
    background-position: right;
  }
}
<div class="loading"></div>
<div class="loading" style="width:150px"></div>
<div class="loading" style="width:120px"></div>

Related