Introduction
A countdown timer is a virtual clock that starts (or stops) counting down from a specific date to mark the start (or finish) of an event. They're commonly used on the landing page of an e-commerce website, under-construction websites, events pages, and a variety of other places.
They're typically used for birthdays, the countdown to the New Year, promotions, and even sports. A countdown timer's main aim is to encourage people to take action, before it's too late - such as purchasing items or services, anticipating and registering for an event, and so on.
Essentially, we would be reserving a certain date in advance. Then, using JavaScript, we can deduct the current date from the specified date, which is done every second, minute, or hour.
In this hands on guide, we will learn how to create a countdown counter, creating a reusable program that can be used on a wide variety of landing pages. We'll construct it entirely in Vanilla JavaScript, and towards the end we'd look at how it might be done with JavaScript date libraries like Moment.js as well.
Note: The source code for the application can also be found on GitHub.
Build a Date Countdown with JavaScript
It is advised that you understand how to create a countdown timer using only JavaScript, rather than a precut solution or a plugin, unless you need to add some more specific functionality that's better taken care of with a library rather than from scratch.
Because it has no dependencies, building this with Vanilla JavaScript allows you to have lightweight code - your website won't be additionally burdened, and you won't need to load external scripts and stylesheets. You'll have greater control, which means you'll be able to design the timer to behave and appear precisely as you want it to, rather than attempting to bend a plugin to your will.
Getting Started
Let's set up a target date, that'll act as the event day we're creating a countdown for. You can also dynamically create this date based on parameters, such as creating a countdown for a user to verify their email address.
We'll set up a static date for brevity's sake:
let interval;
const eventDay = new Date('03/03/2022');
Note: The Date
constructor takes in dates in the (MM/DD/YYYY) format. We've also got a blank interval
for later assignments.
Let's also set up a couple of constant values. Typically, working with time (on the scale of seconds) is done in milliseconds, and most methods/commands accept and return millisecond values.
Based on that, let's define the duration of a second
, minute
, hour
and day
, so we can use those if need be for the countdown:
const second = 1000;
const minute = second * 60;
const hour = minute * 60;
const day = hour * 24;
Creating a Countdown Function
Now to the meat of the logic - the countdown function!
const countDownFn = () => {
// All logic goes in
}
Depending on how often you'd like the timer to update - every second, minute or hour, you'll call the function with in appropriate intervals:
everySecond = setInterval(countDownFn, second)
everyMinute = setInterval(countDownFn, minute)
everyHour = setInterval(countDownFn, hour)
Now, let's get the current date and then subtract it from the eventDay
(in the future) so as to know the difference between them. Then, based on this difference, we'll know how many day(s), hour(s), minute(s) and second(s) left:
let now = new Date();
let timeSpan = eventDay - now;
Note: It is important to place instantiation for the current time (now
) inside the countdown function, since the "current time" changes constantly. When we call the function to update the timer, it'll get the up-to-date time. Secondly, we are using let
instead of const,
since the value changes every second.
Finally, let's add a check as to whether the event day has arrived or not! Once it hits zero, there's no need to count down anymore. For this, we'll make use of an if-else if
statement.
Firstly, let's implement the if
statement to check if the event day set by the user is already in the past:
if (timeSpan <= -today) {
console.log("Unfortunately we have past the event day");
clearInterval(interval);
}
If timeSpan
, the result of the subtraction of the current date and time from the eventDay
is less than or equal to anytime after today - it's negative, or rather, in the past.
Finally - let's check whether the countdown should end:
else if (timeSpan <= 0) {
console.log("Today is the event day");
clearInterval(interval);
return;
}
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
The clearInterval()
function clears the interval, so this logic isn't called on every interval (second, minute, etc.) again.
Finally, we can calculate the number of seconds, minutes, hours and days left, if both of the previous checks evaluate to false
:
else {
const days = Math.floor(timeSpan / day)
const hours = Math.floor((timeSpan % day) / hour)
const minutes = Math.floor((timeSpan % hour) / minute)
const seconds = Math.floor((timeSpan % minute) / second)
console.log(days + ":" + hours + ":" + minutes + ":" + seconds);
}
Instead of printing to the console - let's build a simple HTML page to display the results!
HTML Page
Let's build a small page to display the results. We'll want to have some sort of element for the, say, day, hour, minute and second:
<!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>JS Countdown Timer</title>
</head>
<body>
<div class="date-countdown-container">
<h2 id="day">0</h2>
<p>:</p>
<h2 id="hour">0</h2>
<p>:</p>
<h2 id="minute">0</h2>
<p>:</p>
<h2 id="second">0</h2>
</div>
<script src="./app.js"></script>
</body>
</html>
The app.js
script contains all of the code, including the countDownFn()
. Now, we can alter the output of the function to not print the values to the console, but rather, alter the day
, hour
, minute
and second
divs:
let dayField = document.getElementById('day');
let hourField = document.getElementById('hour');
let minuteField = document.getElementById('minute');
let secondField = document.getElementById('second');
// Constants and countDownFn
const countDownFn = () => {...}
// Set results
dayField.innerHTML = days;
hourField.innerHTML = hours;
minuteField.innerHTML = minutes;
secondField.innerHTML = seconds;
This should work just fine! However, it's not really styled. Let's go ahead and add some CSS to make it much nicer to look at.
CSS - Styling the Countdown Timer
Let's add some style to the timer! We'll add a nicer font, change the background color, centralize the elements, and put them in stylized containers with shadows:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
font-family: 'Poppins', sans-serif;
height: 100vh;
width: 100%;
background: rgb(175, 90, 90);
display: flex;
justify-content: center;
align-items: center;
}
.date-countdown-container{
display: flex;
align-items: center;
gap: 30px;
}
.date-countdown-container h2{
background-color: #ddd;
padding: 20px;
border-radius: 10px;
border: 5px solid #fff;
-webkit-box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0);
box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0);
}
.date-countdown-container p{
background-color: #ddd;
padding: 2px;
border-radius: 10px;
border: 2px solid #fff;
-webkit-box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0);
box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0);
}
With that done - let's add the stylesheet to the <head>
of the HTML file:
<link rel="stylesheet" href="style.css"/>
Running the Application
Finally - we can run the application!
Using Moment.js?
If you're already using Moment.js - there's no harm in using it for this as well. It's absolutely not necessary to have a dependency if you don't need it for something else, but it does offer a useful diff()
function:
const eventDay = moment("2023-06-03");
const now = moment();
const timeSpan = eventDay.diff(now);
Simply said, these three lines are the major variables that aid in the execution of the countdown, and they are the variables you either give or enable to be obtained from the program, in this instance from Moment.js.
If you were to replace the original code's time-handling logic with this - it'd contain:
let dayField = document.getElementById('day');
let hourField = document.getElementById('hour');
let minuteField = document.getElementById('minute');
let secondField = document.getElementById('second');
let interval;
const eventDay = moment("2023-06-03");
// Convert to millisecond
const second = 1000;
const minute = second * 60;
const hour = minute * 60;
const day = hour * 24;
const countDownFn = () => {
const today = moment();
const timeSpan = eventDay.diff(today);
if (timeSpan <= -today) {
console.log("Unfortunately we have past the event day");
clearInterval(interval);
return;
} else if (timeSpan <= 0) {
console.log("Today is the event day");
clearInterval(interval);
return;
} else {
const days = Math.floor(timeSpan / day);
const hours = Math.floor((timeSpan % day) / hour);
const minutes = Math.floor((timeSpan % hour) / minute);
const seconds = Math.floor((timeSpan % minute) / second);
// Set results
dayField.innerHTML = days;
hourField.innerHTML = hours;
minuteField.innerHTML = minutes;
secondField.innerHTML = seconds;
}
};
interval = setInterval(countDownFn, second);
Conclusion
In this hands on guide - we've learned how to make our own countdown timer with only a short JavaScript script, and styled an HTML page to display the countdown, as well as how to utilize Moment.js to perform time arithmetic.