skip to Main Content

My goal is to start a number counter from 0 to 100 as soon as the number enters the viewport.

With my current solution, I have two issues:

  1. The number jumps back to 0 once it finished counting to 100
  2. The counting doesn’t "start" when the element enters the viewport, but rather depends on the scroll state. It counts the further the user scrolls.

Here is my code:

@property --num {
    syntax: "<integer>";
    initial-value: 0;
    inherits: false;
  }

    .number {
      animation-name: counter;
      animation-duration: 5s; 
      animation-timing-function: ease-in-out; 
      animation-delay: 0s;
      animation-direction: normal;
      animation-iteration-count: 1;
      animation-fill-mode: none;
      animation-timeline: view();
      counter-reset: num var(--num);
      font: 800 40px system-ui;
      padding: 2rem;
    }
    .number::after {
      content: counter(num);
    }

    @keyframes counter {
      from {
        --num: 0;
      }
      to {
        --num: 100;
      }
    }


    <span class="number"></span>

2

Answers


  1. You have a few things that need to be updated for this to work.

    1. Define the num variable in a @property block
    2. Get rid of the animation-timeline
    3. Simplify your animation (forwards will stop the fill-mode on its last frame).

    Something like the following:

    @property --num {
      syntax: "<integer>";
      initial-value: 0;
      inherits: false;
    }
    
    .number {
      animation: counter 5s forwards ease-in-out;
      counter-reset: num var(--num);
      font: 800 40px system-ui;
      padding: 2rem;
    }
    
    .number::after {
      content: counter(num);
    }
    
    @keyframes counter {
      from {
        --num: 0;
      }
      to {
        --num: 100;
      }
    }
    <span class="number"></span>
    Login or Signup to reply.
  2. You need to define the animation range. In your case, animation-range: entry 100% exit 0%;. The consider forwards or both to make sure the final value remain after the animation ends

    @property --num {
      syntax: "<integer>";
      initial-value: 0;
      inherits: false;
    }
    
    .number {
      animation: counter linear both;
      animation-timeline: view();
      animation-range: entry 100% exit 0%;
      counter-reset: num var(--num);
      font: 800 40px system-ui;
      padding: 2rem;
      border: 1px solid red;
      
      margin-block: 150vh;
    }
    
    .number::after {
      content: counter(num);
    }
    
    @keyframes counter {
      from {
        --num: 0;
      }
      to {
        --num: 100;
      }
    }
    <div class="number"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search