DEV Community 👩‍💻👨‍💻

Cover image for Simple Countdown Timer Using JavaScript
The Dev Drawer
The Dev Drawer

Posted on • Updated on

Simple Countdown Timer Using JavaScript

One of the standard tools you need to know how to do in JavaScript is...how to manipulate time. To demonstrate this, we will build a countdown timer using vanilla JavaScript and CSS.

This is a simple project, but one that shows you how to manipulate time in JS, customize attributes in CSS, and finally add custom parameters to your JS class.

View This On YouTube

File Structure

index.html
/sass
     style.scss
/js
     init.js
     countdown.js
/css (generated by Sass)
   style.css
   style.min.css
Enter fullscreen mode Exit fullscreen mode

Our HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Countdown Clocks</title>
    <link rel="stylesheet" href="/css/style.min.css">
</head>
<body>
    <h2>Countdown Clock 1</h2>
    <div class="clock" id="clock1">
        <div data-value="days"></div>
        <div data-value="hours"></div>
        <div data-value="minutes"></div>
        <div data-value="seconds"></div>
    </div>
    <script src="/js/countdown.js"></script>
    <script src="/js/init.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Now that we have the basic HTML structure down, we can create the JS class that adds data. Notice we are using data-value so we don't need to add a string in the HTML there, we will modify that will CSS.

Our Countdown JS Class

// class to create a countdown timer
class CountdownTimer {
    // setup timer values
    constructor({ selector, targetDate, backgroundColor = null, foregroundColor = null }) {
        this.selector = selector;
        this.targetDate = targetDate;
        this.backgroundColor = backgroundColor;
        this.foregroundColor = foregroundColor;

        // grab divs on frontend using supplied selector ID
        this.refs = {
            days: document.querySelector(`${this.selector} [data-value="days"]`),
            hours: document.querySelector(`${this.selector} [data-value="hours"]`),
            mins: document.querySelector(`${this.selector} [data-value="minutes"]`),
            secs: document.querySelector(`${this.selector} [data-value="seconds"]`),
        };
    }

    getTimeRemaining(endtime) {
        const total = Date.parse(endtime) - Date.parse(new Date());
        const days = Math.floor(total / (1000 * 60 * 60 * 24));
        const hours = Math.floor((total / (1000 * 60 * 60)) % 24);
        const mins = Math.floor((total / 1000 / 60) % 60);
        const secs = Math.floor((total / 1000) % 60);
        return {
            total,
            days,
            hours,
            mins,
            secs,
        };
    }

    updateTimer({ days, hours, mins, secs }) {
        this.refs.days.textContent = days;
        this.refs.hours.textContent = hours;
        this.refs.mins.textContent = mins;
        this.refs.secs.textContent = secs;
    }

    updateColors() {
        if (this.backgroundColor != null) {
            this.refs.days.style.background = this.backgroundColor;
            this.refs.hours.style.background = this.backgroundColor;
            this.refs.mins.style.background = this.backgroundColor;
            this.refs.secs.style.background = this.backgroundColor;
        }

        if (this.foregroundColor != null) {
            this.refs.days.style.color = this.foregroundColor;
            this.refs.hours.style.color = this.foregroundColor;
            this.refs.mins.style.color = this.foregroundColor;
            this.refs.secs.style.color = this.foregroundColor;
        }
    }

    startTimer() {
        const timer = this.getTimeRemaining(this.targetDate);
        this.updateTimer(timer);
        this.updateColors();
        setInterval(() => {
            const timer = this.getTimeRemaining(this.targetDate);
            this.updateTimer(timer);
        }, 1000);
    }
}
Enter fullscreen mode Exit fullscreen mode

This class will control the div and data-values we need to replace. We create this as a class so we can simply add a few lines of code to add the countdown on any page through our init.js file.

This class takes the selector, the targetDate, and optionally a backgroundColor and foregroundColor. We will pass these values when we call the class.

Calling Our Class

In your init.js file, you can call the countdown class using something like this:

const timer = new CountdownTimer({
    selector: "#clock1",
    targetDate: new Date("September, 21 2022 18:00:00"),
});

timer.startTimer(); 
Enter fullscreen mode Exit fullscreen mode

That code will initialize our class and start a countdown to the date we provided. You can also add a background and foreground color to make it a little more custom. They are not required but it would look something like this:

const timer = new CountdownTimer({
    selector: "#clock1",
    targetDate: new Date("September, 21 2022 18:00:00"),
    backgroundColor: "rgba(0,0,0,.15)",
    foregroundColor: "rgba(0,0,0,.50)",
});

timer.startTimer(); 
Enter fullscreen mode Exit fullscreen mode

You must use both background and foreground colors if you customize one or the other. We have it set up for a null value, but in the end, if you use one, you must use the other.

It is that easy. Now that you have your class set up, you can add your countdown to any div you want. You can also add multiple countdowns on one page. For example:

<h2>Countdown Clock 1</h2>
<div class="clock" id="clock1">
    <div data-value="days"></div>
    <div data-value="hours"></div>
    <div data-value="minutes"></div>
    <div data-value="seconds"></div>
</div>

<h2>Countdown Clock 2</h2>
<div class="clock" id="clock2">
    <div data-value="days"></div>
    <div data-value="hours"></div>
    <div data-value="minutes"></div>
    <div data-value="seconds"></div>
</div>
Enter fullscreen mode Exit fullscreen mode
// setup timer with set textual date in the future
const timer1 = new CountdownTimer({
    selector: "#clock1",
    targetDate: new Date("September, 21 2022 18:00:00"),
});

timer1.startTimer(); 

// setup timer with date set in the future
const timer2 = new CountdownTimer({
    selector: "#clock2",
    targetDate: new Date("September, 21 2022 18:00:00"),
    backgroundColor: "rgba(0,0,0,.15)",
    foregroundColor: "rgba(0,0,0,.50)",
});

timer2.startTimer(); 
Enter fullscreen mode Exit fullscreen mode

Note In order to use this class on multiple divs, you must pass a unique selector that matches the div ID. In this case, we are using #clock1 and #clock2 that matches our div IDs.

Our Countdown Styles

This part is pretty standard if you have ever used CSS or Sass. Note in the Sass, we are customizing the countdown divs using their data-value attribute. This is where we add the text for our div (Days, Hours, Mins, Secs).

body {
    background-color: #38a4ef;
    color:#fff;
    font-size:16px;
    text-align:center;
    font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
}

.clock {
    display:block;
    margin: 0 auto;
    max-width:80%;
    div {
        background-color:rgba(255,255,255,.25);
        color:#fff;
        display:inline-block;
        padding:2rem;
        margin: 0 1rem;
        font-size:2.5rem;
        width: calc(10% - 2rem);
        text-align:center;
        font-weight:bold;
        border-radius:5%;
        &[data-value*="days"]:after, &[data-value*="hours"]:after, &[data-value*="minutes"]:after, &[data-value*="seconds"]:after {
            display:block;
            font-size:.75rem;
            margin-top:.25rem;
            font-weight: 300;
        }
        &[data-value*="days"]:after {
            content:"Days"
        }
        &[data-value*="hours"]:after {
            content:"Hours"
        }
        &[data-value*="minutes"]:after {
            content:"Minutes"
        }
        &[data-value*="seconds"]:after {
            content:"Seconds"
        }
    }
}

@media screen and (max-width: 820px) {
    .clock {
        max-width:90%;
        div {
            width:calc(15% - 2rem)
        }
    }
}

@media screen and (max-width: 767px) {
    .clock {
        max-width:100%;
        div {
            width:calc(30% - 4rem);
            margin:.5rem;
            padding: .5rem;
            font-size:1rem;
            &[data-value*="days"]:after, &[data-value*="hours"]:after, &[data-value*="minutes"]:after, &[data-value*="seconds"]:after {
                font-size:.5rem;
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

We are simply using the :after CSS selector to add the words to the div. This prevents us from having to edit it each time we place it on a page.

I have also added the responsive media queries to our Sass stylesheet so it should work on tablets and mobile phones.

Conclusion

There you have it, a vanilla JavaScript countdown timer. It is a simple project, yet goes over some pretty cool things you can do with JS and CSS. I hope it helps in your future projects.

Top comments (3)

Collapse
 
faaktap profile image
Fakie Tap

You need a

timer1.startTimer(); 
Enter fullscreen mode Exit fullscreen mode

and a

timer2.startTimer(); 
Enter fullscreen mode Exit fullscreen mode

somewhere in your code :-)
Otherwise it will never start. Also idea to do something if timer is passed

Collapse
 
thedevdrawer profile image
The Dev Drawer Author

Also, I am about to do a tutorial on an alarm system using the same type of code that does an alarm sound once it reaches the correct time, you could use that code and add it to this to make it do something is the time has passed. Take a look at it when I push it out in a few days.

Collapse
 
thedevdrawer profile image
The Dev Drawer Author

You are correct. I don't know why but I forgot that part. I will add it to the script.

"I made 10x faster JSON.stringify() functions, even type safe"

☝️ Must read for JS devs