htmlcsscss-animationscss-counter

CSS3 Increment Text After Animation Complete


I am new to CSS animations so I made this little project in which there is a box bouncing and it looks pretty real. I want the text inside the box (at the beginning it is just a 0) to increment by one every time the box bounces/the animation is complete. I tried using a counter but it keeps on resetting.

Here is my code:

* {
  font-family: sans-serif;
}

#container {
  border-bottom: 3px solid #444;
  display: flex;
  height: 330px;
  width: 100%;
}

#oboing {
  align-self: flex-end;
  animation-duration: 2s;
  animation-iteration-count: infinite;
  background-color: black;
  height: 200px;
  margin: 0 auto 0 auto;
  transform-origin: bottom;
  width: 200px;
}

#counter::before {
  color: white;
  position: relative;
  left: 40%;
  top: 40%;
  font-size: 50px;
  content: counter(bounceCount);
}

#oboing {
  animation-name: oboing;
  animation-fill-mode: forwards;
  -webkit-animation-fill-mode: forwards;
  animation-timing-function: cubic-bezier(0.280, 0.840, 0.420, 1);
}

@keyframes oboing {
  0% {
    transform: scale(1, 1) translateY(0);
    counter-reset: bounceCount, calc(counter(bounceCount)+1)
  }
  10% {
    transform: scale(1.1, .9) translateY(0)
  }
  30% {
    transform: scale(.9, 1.1) translateY(-100px);
  }
  50% {
    transform: scale(1.05, .95) translateY(0)
  }
  57% {
    transform: scale(1, 1) translateY(-7px);
  }
  64% {
    transform: scale(1, 1) translateY(0)
  }
  100% {
    transform: scale(1, 1) translateY(0);
    counter-increment: bounceCount;
  }
}

body {
  background: linear-gradient(191deg, #3a22bd, #ea2b0b);
  background-size: 400% 400%;
  height: 100vh;
  overflow: hidden;
  -webkit-animation: Colors 4s ease infinite;
  -moz-animation: Colors 4s ease infinite;
  -o-animation: Colors 4s ease infinite;
  animation: Colors 4s ease infinite;
}

@-webkit-keyframes Colors {
  0% {
    background-position: 0% 52%
  }
  50% {
    background-position: 100% 49%
  }
  100% {
    background-position: 0% 52%
  }
}

@-moz-keyframes Colors {
  0% {
    background-position: 0% 52%
  }
  50% {
    background-position: 100% 49%
  }
  100% {
    background-position: 0% 52%
  }
}

@-o-keyframes Colors {
  0% {
    background-position: 0% 52%
  }
  50% {
    background-position: 100% 49%
  }
  100% {
    background-position: 0% 52%
  }
}

@keyframes Colors {
  0% {
    background-position: 0% 52%
  }
  50% {
    background-position: 100% 49%
  }
  100% {
    background-position: 0% 52%
  }
}
<div id='container'>
  <div id='oboing'>
    <span id='counter'>0</span>
  </div>
</div>

I am open to any suggestions including CSS, HTML, Jquery, JS, etc...

I would also appreciate it if someone could also explain why their code works... Many times I see answers on this website that have only code and no explaining. Please explain!


Solution

  • By it's definition, counter-increment is a non-animatable css property - that's why you're not being successful in using it in your animation. You would have to use a javascript function to count the bounces. As the animation duration is 2 seconds, one approach would be to use a set-interval approach and increment your counter every 2 seconds.

    document.getElementById('counter').innerHTML = 0; 
    function increment() {
         var x = document.getElementById('counter').innerHTML;
         //if we declare the x value as 0, it will keep resetting, 
         //so instead, put we retrieve the initial value from the span 
         //and set the variable to that value
         x++;
         //increase by 1
        document.getElementById('counter').innerHTML = x; //set span value
    }
    setInterval(increment, 2000);  //1000ms in 1 sec
    * {
      font-family: sans-serif;
    }
    
    #container {
      border-bottom: 3px solid #444;
      display: flex;
      height: 330px;
      width: 100%;
    }
    
    #oboing {
      align-self: flex-end;
      animation-duration: 2s;
      animation-iteration-count: infinite;
      background-color: black;
      height: 200px;
      margin: 0 auto 0 auto;
      transform-origin: bottom;
      width: 200px;
    }
    
    #counter {
      color: white;
      position: relative;
      left: 40%;
      top: 40%;
      font-size: 50px;
    }
    
    #oboing {
      animation-name: oboing;
      animation-fill-mode: forwards;
      -webkit-animation-fill-mode: forwards;
      animation-timing-function: cubic-bezier(0.280, 0.840, 0.420, 1);
    }
    
    @keyframes oboing {
      0% {
        transform: scale(1, 1) translateY(0);
      }
      10% {
        transform: scale(1.1, .9) translateY(0)
      }
      30% {
        transform: scale(.9, 1.1) translateY(-100px);
      }
      50% {
        transform: scale(1.05, .95) translateY(0)
      }
      57% {
        transform: scale(1, 1) translateY(-7px);
      }
      64% {
        transform: scale(1, 1) translateY(0)
      }
      100% {
        transform: scale(1, 1) translateY(0);
      }
    }
    
    body {
      background: linear-gradient(191deg, #3a22bd, #ea2b0b);
      background-size: 400% 400%;
      height: 100vh;
      overflow: hidden;
      -webkit-animation: Colors 4s ease infinite;
      -moz-animation: Colors 4s ease infinite;
      -o-animation: Colors 4s ease infinite;
      animation: Colors 4s ease infinite;
    }
    
    @-webkit-keyframes Colors {
      0% {
        background-position: 0% 52%
      }
      50% {
        background-position: 100% 49%
      }
      100% {
        background-position: 0% 52%
      }
    }
    
    @-moz-keyframes Colors {
      0% {
        background-position: 0% 52%
      }
      50% {
        background-position: 100% 49%
      }
      100% {
        background-position: 0% 52%
      }
    }
    
    @-o-keyframes Colors {
      0% {
        background-position: 0% 52%
      }
      50% {
        background-position: 100% 49%
      }
      100% {
        background-position: 0% 52%
      }
    }
    
    @keyframes Colors {
      0% {
        background-position: 0% 52%
      }
      50% {
        background-position: 100% 49%
      }
      100% {
        background-position: 0% 52%
      }
    }
    <div id='container'>
      <div id='oboing'>
        <span id='counter'>0</span>
      </div>
    </div>

    Hope this clears things up for you! :)