New Tutorials:   NUMPY    TKINTER    KOTLIN    JAVASCRIPT    SASS/SCSS    PL/SQL    Matplotlib    C++ Programs
CLOSE
   Javascript  HTML  CSS  
   Technology    Programming

How to Build an Animated Counter with JavaScript

         
  FEBRUARY 10, 2021   by nemo011

I am sure at some point in your life while browsing the web, you have found a web page that shows an animated counter. A counter that starts from 0 and goes all the way up to some given number. Here is an example of how such a counter looks.

javascript counter

In this article, we are going to build exactly a counter like this.

Prerequisites:

This article is going to be a shorter one. So, without wasting any more time, let’s get started.

The Markup (HTML)

The markup for this example has one container. All our elements are going to be inside a parent container. All the individual counter elements, including the icons, text, and time, will be under another container. Let’s see the markup.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Loading Counter</title>
    <link rel="stylesheet" href="styles.css">
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Nunito:[email protected];900&display=swap" rel="stylesheet">
    <script src="script.js" defer></script>
</head>

<body>
    <div class="container">
        <div class="heading">
            Counting Upto the Limit
        </div>
        <div class="counter-container">
            <div class="counter">
                <img src="./icons/iconmonstr-time-19.svg" alt="timer" srcset="" class="icon">
                <h3 data-target="15000" class="count">0</h3>
                <h6>Work Hours</h6>
            </div>
            <div class="counter">
                <img src="./icons/iconmonstr-coffee-11.svg" alt="Coffee" srcset="" class="icon">
                <h3 data-target="1200" class="count">0</h3>
                <h6>Cups of Coffee</h6>
            </div>
            <div class="counter">
                <img src="./icons/iconmonstr-weather-112.svg" alt="night" srcset="" class="icon">
                <h3 data-target="500" class="count">0</h3>
                <h6>Sleepless Nights</h6>
            </div>
        </div>
    </div>
</body>

</html>

As you can see, at the top, we include our stylesheet file and the scripts file. The defer tag in the script tag will ensure that the javascript loads after the HTML completes the loading. We are using the Nunito google font. All the icons in this tutorial are from iconmonstr. I have downloaded these three icons for the sake of this tutorial. Inside the container div, we are adding a div that will hold the heading. We are calling this div heading. Then, we are creating another div called counter-container, that will keep all our counters. Each counter has a counter div. The counter div holds icon, an H3 tag with 0 inside it, and an H6 tag with some text inside. Look closely at the H3 tag. This tag has a class of count and an attribute called data-target. The data-* attribute allows us to store extra information. Any user-defined name that starts with data- in front of it will be counted as a non-standard attribute.

These values can be used in JavaScript. Reading these values in JavaScript is also very simple. We can use the getAttribute method to read them. You’ll see it when we access it in JavaScript. In our code, these data-target attributes will say how much we want to count. For example, 15000 in the first attribute will count from 0 to 15000. Because our base value is zero, this is why we are adding 0 to the H3s.

So, our markup is done. Now, let’s jump to the CSS part.

Styling the Counter (CSS)

For this example, we are going to use extremely simple styles. Just a few flexboxes to get the positions we want.

Like all the other tutorials, our first thing in styling this is to reset the default values and change the box-sizing to border-box.

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

Because we are going to use a google font Nunito, we have to define it in the body of our document. I am also going to add a background color.

body {
    font-family: 'Nunito', sans-serif;
    background: #fbf7f4;
}

The next thing is the container.

.container {
    width: 80%;
    margin: auto;
}

These styles will restrict the container to a width of 80% of the parent. The auto margin will center the container. Now, let’s style the heading.

.heading {
    text-align: center;
    font-size: 3.5rem;
    font-weight: bold;
    padding: 5rem 0;
}

I don’t think that I have to explain anything here. The styles are pretty self-explanatory. Let’s move on to styling the counter-container now.

.counter-container {
    display: flex;
    justify-content: space-around;
    align-items: center;
}

We want all the counters to be centered. To do this, we will take the help of flexbox. If you don’t know about flexboxes, here is a two-part article for you,

Our counters are now centered. Let's center the texts inside the counters. We can use the text-align property here. Each counter is inside the counter div. Let's target the div and center the texts.

.counter {
    text-align: center;
}

Now let's style the headings inside the counters. It is also very simple. I am going to paster the codes below.

.counter h3 {
    padding: 0.5rem 0;
    font-size: 2.5rem;
    font-weight: 800;
}

.counter h6 {
    font-size: 2rem;
    padding-bottom: 1rem;
}

Finally, let's increase the icon size.

.icon {
    height: 5rem;
    width: auto;
}

We are extending the height only and setting the width to auto to adjust the width automatically.

And we are done with the CSS part.

The JavaScript

Inside our JavaScript, we only need to target a single DOM. If you go back to the HTML and check the counter H3, you’ll see that we have a class inside the H3 tag. It is the count tag and is available on every counter header. So, in JavaScript, to target this DOM we can use the querySelectorAll property. This property will select all the count classes. Another thing that we need in our JavaScript is the speed variable. A speed variable will be used to control the counter’s speed, i.e., how fast it counts.

const counters = document.querySelectorAll('.count');
const speed = 200;

Now, we will loop through each of the counters and execute a function. This function will do all the counting. Because we are going to run a function inside the loop, we can use the forEach loop. We have to pass in at least one parameter in a forEach loop. This element is the current value of the loop. Let’s say it counter for our app.

Inside the forEach loop, we will create a function that will do all the work. Let’s call this function updateCount.

counters.forEach((counter) => {
  const updateCount = () => {
    const target = parseInt(counter.getAttribute('data-target'));
    const count = parseInt(counter.innerText);
    const increment = Math.trunc(target / speed);


  };
  updateCount();
});

Let’s first understand the code up to the above part. The target variable will hold the target that is defined using the data- attribute in our HTML. As you can see, to get the data values, we use the getAttribute method. And inside the method, we pass in the attribute's complete name, including data- tag. The parseInt in front of it will convert the value into an integer because, by default, the return value is of string type. Then we take the value of the text that is inside our H3. At the start, this value will be 0. So, why are we not using it directly? Because the way our counter works is that it adds a number to the inner text of the H3 until it reaches the target value. For this, we have to keep track of the value that is generated each time by adding the increment value. We are also converting it to an integer. We can also use a + sign in place of the parseInt. The increment variable holds the number that is to be added after a specified time. We calculate it by dividing the target by speed. The Math.trunc will round off the value that we get by dividing. In JavaScript, there are multiple ways to round off a value. Here’s an article that talks about the different rounding methods.

The next thing is to check if we have reached the target value. And if the current value is less than the target value then we add up our increment value until we reach the target. This is a simple if-else statement.

if (count < target) {
      counter.innerText = count + increment;
      setTimeout(updateCount, 1);
    } else {
      count.innerText = target;
    }

First, we are adding our increment value to the counter and changing the DOM value using counter.innerText. We are passing two parameters inside the setTimeout function. The setTimeout function executes a specific function after a given period of time. In our case, the first parameter is the updateCount function, and the 1 represents one millisecond. So, it will execute the updateCount function after every one millisecond until the count value is less than the target value. Otherwise, we set the inner text to the target value. The only step that is left, is to call our updateCount function. So, the complete JavaScript will look like this,

const counters = document.querySelectorAll('.count');
const speed = 200;

counters.forEach((counter) => {
  const updateCount = () => {
    const target = parseInt(counter.getAttribute('data-target'));
    const count = parseInt(counter.innerText);
    const increment = Math.trunc(target / speed);

    if (count < target) {
      counter.innerText = count + increment;
      setTimeout(updateCount, 1);
    } else {
      counter.innerText = target;
    }
  };
  updateCount();
});

And our counter is done. Here is a complete working version of our counter.

You can also find the complete code on this Github repo.

Conclusion

So, this was a pretty easy tutorial. It is a great one to practice your basic JavaScript knowledge. I hope you enjoyed building this one. Here are two more such projects that will help you to grow your JavaScript knowledge.

For more such tutorials and projects, keep visiting Studytonight.


RELATED POSTS



Subscribe and receive amazing posts directly in your inbox.