How to make a progress bar that goes from 0 to 100% with CSS only?


I need to make a progress bar that starts from 0 and goes to 100%. But I need to do only with CSS, and besides that, I need it when it reaches 100%, start again from 0.

Although there is some information about this progress bar, I need it to last exactly 6 seconds and when it reaches 100%, skip to 0%.

Has anyone ever had to do something similar?

asked by anonymous 14.12.2017 / 13:23

3 answers


Would that be, young man?

    height: 15px;
    background-color: #777;
    position: relative;

.progress .progress-bar{
   position: absolute;
   height: 100%;
   background-color: #add555;
   animation: progress-animation 6s infinite;

@keyframes progress-animation{
    0% { width: 0%; }
    100% { width: 100%}
<div class="progress">
    <div class="progress-bar"></div>


@keyframes is intended to specify an animation for the element. You can define the steps for each frame of the animation through a CSS style block declared by from or to , or even set by percentages - as I did above, indicating that in 0% (the beginning) a animation it should contain the size 0% and with 100% it will have 100% size.


@keyframes example{
    0% {
        /* frame inicial da animação, poderia ser usado "from" */

   50% {
      /* frame do "meio" da animação */

   100% {
      /* último frame da animação */


Example with from :

@keyframes example {
      from {
          /* início da animação */
      to {
         /* final da animação */

To use an animation declared with @keyframes , you must use the animation attribute in the desired selector setting, and you can set interval animation or repetitions.


 .example {
    /* use a animação "example" no intervalo de 2 segundos infinitamente */
    animation: example 2s infinite;

Note : The animation property is only a shortcut to the various properties that can be set to configure an animation. They are:

  • animation-name
  • animation-duration
  • animation-timing-function
  • animation-delay
  • animation-iteration-count
  • animation-direction
  • animation-fill-mode
  • animation-play-state

Read more at MDN

14.12.2017 / 13:35

My idea follows the same as Wallace's answer , with the alternative of not having to create more than one element html to deal with the visual "internal" progress, the bar that increases the width property. Leveraging <div> itself and using the pseudo element ::after (or ::before ) you can do this:

@keyframes loading {
  from { width: 0 }
  to { width: 100% }

div {
  background: #E7E7E7;
  position: relative;
  height: 8px;
  width: 100%

div::after {
  animation: loading 6s infinite ease-in-out;
  background: #897FBA;
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0
14.12.2017 / 13:36

It has a different way of doing it using linear-gradiente , so you do not need more than one tag or use pseudo-element .

Imagine that you have a linear gradient as the% of a container , and that this gradient is equally divided with 50% of the width with one color and the others 50% with another color.

Now with background you put this background-size with 200% of background of container . This way each half of the gradient now occupies 100% of the container width.

Nowwithwidthandbackground-positionwemake@keyframeswalk100%tooneside,showing100%oftheothercolorthatwas"hidden" out of the container . >

The animation

On the background property it is composed as follows in shorthand :

animation: name duration timing-function delay iteration-count direction fill-mode;

Or Longhand ( animation values)

animation-name: none
animation-duration: 0s
animation-timing-function: ease
animation-delay: 0s
animation-iteration-count: 1
animation-direction: normal
animation-fill-mode: none
animation-play-state: running

In your case you need to focus on initial (animation name declared in name ), @keyframes (have you want animation to last 6s) and duration (how many times will the animation repeat itself iteration-count "eternal loop") In this Mozilla documentation you can learn more: link

Once defined this will work on the animation intervals built into at-rule infinite . Since I want you to first have a range of 1s to see the bar 100% empty at the beginning and then a range of 1s for you to see the bar 100% complete at the end I will repeat some values at the beginning and at the end of @keyframes The comment is in the code below:

OBS: As the animation has 6 seconds I will divide 100 by 6, so we have 6 intervals of 16.66% representing each second of animation. In the first second and in the last second the bar will stop for 1 second. If you do not want this effect just put it that way. So the bar completes straight, without a delay at the beginning and end to see the two complete states of the bar:

/* estado inicial da barra */
  0% {
    background-position: 99% 0;
/* estado final da barra */
  100% {
      background-position: 0 0;

For a better understanding of how the fractioning of the animation works and the creation of this delay, see the comment I left in the code below:

.barra {
    height: 16px;
    width: 50%;
    border-radius: 8px;
    margin: 10px auto;
 /* gradiente com 2 cores */
    background-image: linear-gradient(to right, #bada55 0, #bada55 50%, gray 50%);
 /* agradiente com 200% da largura do container 101% pra cada cor */
    background-size: 202% 100%;
 /* move o backgrount para mostrar apenas a primeira cor */
    background-position: 99% 0;
 /* animação que move o background para mostrar a segunda cor */
    animation: anima 6s ease-in-out infinite;
 /* coloquei 500ms de delay para vc poder ver a barra 100% "vazia" antes de iniciar a animação */

@keyframes anima {
    0% {
      /* movemo o background para mostrar apenas 100% de uma cor */
      background-position: 99% 0;
    /* do 0% do tempo da animação até 16,66% do tempo a barra permance parada */
    16.66% {
        background-position: 99% 0;
    /* esse intervalo representa 4 segundos do tempo da animação até a barra fica 100% cheia */
    83.34% {
        background-position: 0 0;
    /* esse intervalo de 83,34% a 100% representa 1 segundo da animação e a barra fica cheia por 1s antes de reiniciar*/
    100% {
        /* de 75% a 100% eu repito o estado da propriedade para vc ter um tempo de ver a barra 100% completa antes de reiniciar a animação */
        background-position: 0 0;
<div class="barra"></div>

An image to better explain the technique.

The blue border is the container , and the moving background is @keyframes . % W / o% has 200% parent width, so each color that has 50% of the gradient actually gets 100% parent width. Then by setting the horizontal value of background to background it is possible to make the bar wiggling, giving the impression that it is completing the container .

Browsersupport:Accordingto link this template works from IE10 up, Chrome, Fire Fox, Safari, etc ...

04.10.2018 / 01:40