DEV Community

Karthikeyan P
Karthikeyan P

Posted on • Edited on

5 3

How to animate horizontal bars sequentially in CSS3?

I usually use JavaScript to animate items on webpage sequentially. Recently, I have understood that I can use CSS3 keyframes to animate items sequentially. To demonstrate that, I animate bars (increasing width from left to right) sequentially here.

So, my HTML structure looks like this; Each bar is represented here in a div HTML element with a class bar.

<div class="bar-container">

  <div class="bar bar_0">

  </div>
  <div class="bar bar_1">

  </div>
  <div class="bar bar_2">

  </div>
  <div class="bar bar_3">

  </div>
  <div class="bar bar_4">

  </div>
  <div class="bar bar_5">

  </div>

</div>
Enter fullscreen mode Exit fullscreen mode

The bars are animated one after the other; the bars of different width and their actual bar animation duration depends on their width. I use SASS for this example.

I first set the width and height of the bar and their background as you can see below.

.bar {
  width: 100px; 
  height: 50px;
  background-color: rgba(66, 237, 148, 0.6);
}

Enter fullscreen mode Exit fullscreen mode

Now I set specific width to each bar using their unique CSS classname. As you can see each bars set different width and &.bar_5 is not defined styles because I want it to inherit width property from the common class .bar and other properties will be set later. I have used percentage value for the bar which is related to browser window width.

.bar {
  width: 100px;
  height: 50px;
  background-color: rgba(66, 237, 148, 0.6);

  &.bar_0 {
    width: 30%;
  }
  &.bar_1 {
    width: 50%;
  }
  &.bar_2 {
    width: 60%;
  }
  &.bar_3 {
    width: 70%;
  }
  &.bar_4 {
    width: 75%;
  }
}

Enter fullscreen mode Exit fullscreen mode

The above HTML and CSS together will render as.

Bars

Now the most interesting part, Animation. Since there are 6 bars we will have to have six different @keyframes to animate them sequentially. Let me show the @keyframes first then I explain them in details.

$percentages: (30, 50, 60, 65, 75, 100);
$factor: 20;
$interval: 0.5;
$previousAnimation: 0;
@for $i from 1 through 6 {
  @keyframes bar_animate_#{$i - 1} {
    @if $i > 2      
     {
      $previousAnimation: $previousAnimation + ($factor * nth($percentages, $i - 1) / 100) + $interval;
      0%, #{($previousAnimation)}% {
      transform: scaleX(0);
      transform-origin: left;
     } 
    }
    @else if $i == 2{
      $previousAnimation: $previousAnimation + ($factor * nth($percentages, $i - 1) / 100) + $interval;
      0%, #{$previousAnimation }%
      {
      transform: scaleX(0);
      transform-origin: left;
      }
    }
    @else
    {
      0%
      {
      transform: scaleX(0);
      transform-origin: left;
      }
    }

    #{$previousAnimation + ($factor * nth($percentages, $i) / 100)}%, 100%
      {
      transform: scaleX(1);
      transform-origin: left;
      }
  }
}
Enter fullscreen mode Exit fullscreen mode

Basically, I animate from scaleX(0) to scaleX(1) with transform-origin. The reason to have transform-origin is to tell transform property to start the scaling from left rather than from center (by default).

The important part is animation starting timing; it is represented here in %(percentage). Let's add animation to bar elements.

.bar {
  width: 100px;
  height: 50px;
  background-color: rgba(66, 237, 148, 0.6);
  animation-duration: 10s; //Added now

  &.bar_0 {
    width: 30%;
    animation-name: bar_animate_0; //Added now
  }
  &.bar_1 {
    width: 50%;
    animation-name: bar_animate_1; //Added now
  }
  &.bar_2 {
    width: 60%;
    animation-name: bar_animate_2; //Added now
  }
  &.bar_3 {
    width: 70%;
    animation-name: bar_animate_3; //Added now
  }
  &.bar_4 {
    width: 75%;
    animation-name: bar_animate_4; //Added now
  }
  &.bar_5{
    animation-name: bar_animate_5; //Added now
  }
}
Enter fullscreen mode Exit fullscreen mode

I have added animation-duration and animation-name; the overall animation duration is same for all element but actual bar animation duration and start timing are different. If you look closely I animate bar_0 from 0s to 0.6s (0% to 6% of 10s) and rest of the animation duration stays the same and also during this time, all other bars do not animate because they are set to transform: scaleX(0) which basically set width to 0 (hidden). Then, I give .5s (.5%) duration for next bar element to start animation then next bar animate for 1s and so the same logic goes till the last bar element.

This is how I was able to animate the elements sequentially with just CSS3 @keyframes.

CodePen DEMO

If you have any questions or suggestions please write below. Thanks

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (3)

Collapse
 
washingtonsteven profile image
Steven Washington • Edited

Pretty cool!

There's also animation-delay, which is helpful for spacing out the timing of animations: developer.mozilla.org/en-US/docs/W...

Side note: one reason why I like preprocessors (my go to is Sass) is that necessarily repetitive CSS can be encapsulated in a for loop:

// note: using $factor1 and $factor2 for the multiplication factors to 
// determine the animation percentages
@for $i from 0 through 5 {
  @keyframes bar_animate_#{$i} {
    0%,
    #{$i * $factor1}% {
      transform: scaleX(0);
      transform-origin: left;
    }
    #{$i * $factor2}%,
    100% {
      transform: scaleX(1);
      transform-origin: left;
    }
  }
}

And similarly for the .bar_[i] classes.

One more thing, looks like the CSS in that last block is correct, you set all the animations to bar_animate_5. The Codepen is correct though.

Collapse
 
forethought_de profile image
Karthikeyan P

Thanks for suggesting improvement and pointing out the mistake. I have corrected the mistake now. I will refactor it in the evening.

Collapse
 
forethought_de profile image
Karthikeyan P

@Steven, I have refactored the animation to use Sass's for loop and updated the article. Many thanks for suggesting the improvement.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay