Summary: in this tutorial, you’ll learn how to develop a reusable JavaScript countdown timer.
What is a countdown timer
A countdown timer is a virtual clock running on a landing page. And it counts down from a certain date to indicate the beginning (or the end) of an event.
On eCommerce websites, you can use a countdown timer to display the beginning (or the end) of an offer. The purpose of the countdown timer is to urge customers to take actions such as buying products or services.
In this tutorial, you’ll learn how to create a countdown timer in JavaScript from scratch. And you’ll learn how to use it to build a New Year countdown timer.
The following shows the final New Year countdown landing page.
Note that the countdown timer that you’re going to build is reusable so you can use it on any landing page. In addition, you can use this countdown to create multiple countdown timers on a single page.
Create the project structure
First, create a project folder called countdown-timer
. Inside that folder, create three subfolders: js
, css
, and img
that will store the JavaScript, CSS, and image files.
Second, create the style.css
in the css
folder, app.js
and countdown.js
files in the js
folder, and the index.html
in the countdown-timer
folder:
Third, download this firework picture and copy it to the img
folder. You’ll use this picture as the background of the New Year countdown page.
The project structure will look like this:
Create the HTML page
The HTML page is quite simple because you’ll generate most of the HTML code from JavaScript.
The following shows the complete HTML page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Countdown Timer - New Year Countdown</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>New Year Countdown</h1>
<div class="countdown-timer"></div>
<div class="message"></div>
<div class="year"></div>
<script src="js/countdown.js"></script>
<script src="js/app.js"></script>
</body>
</html>
Code language: HTML, XML (xml)
In the index.html
file, you place a link to the style.css
file in the <head>
section and the countdown.js
and app.js
files in the <body>
section.
Note that the countdown.js
file must appear before the app.js
file because the app.js
will use the objects in the countdown.js
file.
The <body>
section has four elements:
- A heading 1 (
<h1>
) . This element will show a heading. It can be anything that describes the countdown e.g., New Year Countdown. - A
<div>
with the classcountdown-timer
. This element will display the countdown. - A
<div>
with themessage
class. This element will display the message when the countdown completes. - And a
<div>
with theyear
class. This element will show the New Year e.g., 2021.
A quick overview of the Date object
To create the timer, you’ll need to work with the Date
object, which is available in all web browsers.
The Date
object represents a single moment in time. It contains a number that represents the milliseconds since January 1, 1970 UTC.
The following shows how to create a new Date
object that represents the current date and time:
const now = new Date();
Code language: JavaScript (javascript)
And this example shows how to call the getTime()
method of the Date
object to get the number of milliseconds since January 1, 1970 00:00:00 UTC
:
const time = now.getTime();
console.log(time);
Code language: JavaScript (javascript)
To create a new Date
object with a specified date and time, you can pass a date string into the Date()
constructor like this:
const d = new Date('February 02, 2020 01:02:03');
console.log(d.getTime()); // 1580580123000
Code language: JavaScript (javascript)
To calculate the number of milliseconds between two times, you call the getTime()
method and use the -
operator. For example:
const d1 = new Date('September 17, 2020 00:00:00');
const d2 = new Date('September 19, 2020 01:00:00');
const time = d2.getTime() - d1.getTime();
console.log(time); // 176400000
Code language: JavaScript (javascript)
Calculate the remaing time
The countdown timer will need to calculate the remaining days, hours, minutes, and seconds from a number of milliseconds and display this information on a webpage.
The following declare a time variable with the value 150000 milliseconds:
const time = 150000; // ms
Code language: JavaScript (javascript)
To convert milliseconds to minutes, you divide the milliseconds by 1000 to get the seconds and divide the seconds by 60 to get the minutes. For example:
console.log(time / 1000 / 60);
Code language: JavaScript (javascript)
Output:
2.5
Code language: CSS (css)
To get the remaining minutes (2), you use the Math.floor()
function:
const minutes = Math.floor(time / 1000 / 60);
console.log(minutes); // 2
Code language: JavaScript (javascript)
To get the remaining seconds (30), you use the modulus operator ( % ) that returns the division remainder:
const seconds = Math.floor(time / 1000) % 60;
console.log(seconds); // 30
Code language: JavaScript (javascript)
Develop the CountDown class
First, create a new CountDown
class in the countdown.js
file:
class CountDown {
}
Code language: JavaScript (javascript)
The CountDown
class should be initialized with three arguments:
- an expired date.
- a callback that is responsible for rendering the countdown timer.
- and another callback that will be called when the countdown completes.
The constructor of the CountDown
class will look like this:
class CountDown {
constructor(expiredDate, onRender, onComplete) {
this.onRender = onRender;
this.onComplete = onComplete;
// handle the expired Date
..
}
}
Code language: JavaScript (javascript)
Based on the expiredDate
argument, you can calculate the remaining time in milliseconds:
const currentTime = new Date().getTime();
const timeRemaining = expiredDate.getTime() - currentTime;
Code language: JavaScript (javascript)
Since you’ll need to access the remaining time (timeRemaining
) across methods of the class, you should define it as a property of the CountDown
class.
The setExpiredDate() method
The following defines a new method called setExpiredDate()
that initializes the timeRemaining
property:
setExpiredDate(expiredDate) {
// get the current time
const currentTime = new Date().getTime();
// calculate the remaining time
this.timeRemaining = expiredDate.getTime() - currentTime;
}
Code language: JavaScript (javascript)
If the timeRemaining
is greater than zero, the setExpiredDate()
method will execute the start()
method to start the timer. Otherwise, it’ll execute the complete()
method.
The setExpiredDate()
will look like this:
setExpiredDate(expiredDate) {
// get the current time
const currentTime = new Date().getTime();
// calculate the remaining time
this.timeRemaining = expiredDate.getTime() - currentTime;
// should the countdown completes or start
this.timeRemaining > 0 ?
this.start() :
this.complete();
}
Code language: JavaScript (javascript)
Note that we use the ternary operator ?:
to execute the complete()
or start()
method based on the value of the this.timeRemaining
property.
The complete() method
The complete()
method checks if the onComplete
callback is passed and invoke it. If the onComplete
isn’t available, the complete()
won’t do anything.
complete() {
if (typeof this.onComplete === 'function') {
onComplete();
}
}
Code language: JavaScript (javascript)
start() method
The start()
method reduces the timeRemaining
property every second (1000 ms).
If the remaining time is less than zero, the start()
method will:
- First, call the
complete()
method. - Second, clear the timer using the
clearInterval()
function.
start() {
// setup a timer
const intervalId = setInterval(() => {
// update the timer
this.timeRemaining -= 1000;
if (this.timeRemaining < 0) {
// call the callback
complete();
// clear the interval if expired
clearInterval(intervalId);
}
}, 1000);
}
Code language: JavaScript (javascript)
In case the remaining time is greater than zero, the start()
method should call a method that executes the onRender
callback.
The getTime() method
The following getTime()
method returns an object that contains the remaining days, hours, minutes, and seconds based on the timeRemaining
property.
getTime() {
return {
days: Math.floor(this.timeRemaining / 1000 / 60 / 60 / 24),
hours: Math.floor(this.timeRemaining / 1000 / 60 / 60) % 24,
minutes: Math.floor(this.timeRemaining / 1000 / 60) % 60,
seconds: Math.floor(this.timeRemaining / 1000) % 60
};
}
Code language: JavaScript (javascript)
The update() method
The following defines the update()
method that calls the onRender()
callback with the current remaining time object returned by the getTime()
method:
update() {
if (typeof this.onRender === 'function') {
this.onRender(this.getTime());
}
}
Code language: JavaScript (javascript)
The start()
method will call the update()
method at the beginning and every second after that:
start() {
// update the countdown
this.update();
// setup a timer
const intervalId = setInterval(() => {
// update the timer
this.timeRemaining -= 1000;
if (this.timeRemaining < 0) {
// call the callback
complete();
// clear the interval if expired
clearInterval(intervalId);
} else {
this.update();
}
}, 1000);
}
Code language: JavaScript (javascript)
The following shows the complete CountDown
class:
class CountDown {
constructor(expiredDate, onRender, onComplete) {
this.setExpiredDate(expiredDate);
this.onRender = onRender;
this.onComplete = onComplete;
}
setExpiredDate(expiredDate) {
// get the current time
const currentTime = new Date().getTime();
// calculate the remaining time
this.timeRemaining = expiredDate.getTime() - currentTime;
this.timeRemaining <= 0 ?
this.complete() :
this.start();
}
complete() {
if (typeof this.onComplete === 'function') {
onComplete();
}
}
getTime() {
return {
days: Math.floor(this.timeRemaining / 1000 / 60 / 60 / 24),
hours: Math.floor(this.timeRemaining / 1000 / 60 / 60) % 24,
minutes: Math.floor(this.timeRemaining / 1000 / 60) % 60,
seconds: Math.floor(this.timeRemaining / 1000) % 60
};
}
update() {
if (typeof this.onRender === 'function') {
this.onRender(this.getTime());
}
}
start() {
// update the countdown
this.update();
// setup a timer
const intervalId = setInterval(() => {
// update the timer
this.timeRemaining -= 1000;
if (this.timeRemaining < 0) {
// call the callback
complete();
// clear the interval if expired
clearInterval(intervalId);
} else {
this.update();
}
}, 1000);
}
}
Code language: JavaScript (javascript)
Build the New Year countdown
First, create a new function called getNewYear()
method that returns the New Year:
const getNewYear = () => {
const currentYear = new Date().getFullYear();
return new Date(`January 01 ${currentYear + 1} 00:00:00`);
};
Code language: JavaScript (javascript)
Second, select and update the .year
element. It’ll show a four-digit year number of the New Year e.g., 2021:
// update the year element
const year = document.querySelector('.year');
year.innerHTML = getNewYear().getFullYear();
Code language: JavaScript (javascript)
Third, select the .countdown-timer
, .message
and h1
elements:
// select elements
const app = document.querySelector('.countdown-timer');
const message = document.querySelector('.message');
const heading = document.querySelector('h1');
Code language: JavaScript (javascript)
Fourth, define a format function that pad a number with the '0'
if the number is less than 10. For example, 5 will be 05
. But 10 will remain the same.
const format = (t) => {
return t < 10 ? '0' + t : t;
};
Code language: JavaScript (javascript)
Fifth, define a render()
method that composes HTML markup from the time object and update it to the .countdown-timer
element. It’ll show the remaining days, hours, minutes, and seconds.
const render = (time) => {
app.innerHTML = `
<div class="count-down">
<div class="timer">
<h2 class="days">${format(time.days)}</h2>
<small>Days</small>
</div>
<div class="timer">
<h2 class="hours">${format(time.hours)}</h2>
<small>Hours</small>
</div>
<div class="timer">
<h2 class="minutes">${format(time.minutes)}</h2>
<small>Minutes</small>
</div>
<div class="timer">
<h2 class="seconds">${format(time.seconds)}</h2>
<small>Seconds</small>
</div>
</div>
`;
};
Code language: HTML, XML (xml)
Fifth, when the countdown completes, it shows a message e.g., "Happy New Year"
.
The following showMessage()
function displays the Happy New Year
message. In addition, it clears the contents of the .countdown-timer
element and hides the heading element:
const showMessage = () => {
message.innerHTML = `Happy New Year ${newYear}!`;
app.innerHTML = '';
heading.style.display = 'none';
};
Code language: JavaScript (javascript)
Sixth, the New Year countdown should show the Happy New Year greeting message for a period of time and then displays the countdown for the New Year again.
The following defines a function that hides the greeting message and shows the heading element:
const hideMessage = () => {
message.innerHTML = '';
heading.style.display = 'block';
}
Code language: JavaScript (javascript)
Seventh, define a complete()
function that shows the message for a period of time and then hides it. In addition, it sets the expiredDate
to the New Year:
const complete = () => {
showMessage();
// restart the countdown after showing the
// greeting message for a day ()
setTimeout(() => {
hideMessage();
countdownTimer.setExpiredDate(getNewYear());
}, 1000 * 60 * 24);
};
Code language: JavaScript (javascript)
Finally, create the new CountDown
instance and pass the New Year date, render
function, and complete
function into its constructor:
const countdownTimer = new CountDown(
getNewYear(),
render,
complete
);
Code language: JavaScript (javascript)
The following shows the complete app.js
file:
// Get the new year
const getNewYear = () => {
const currentYear = new Date().getFullYear();
return new Date(`January 01 ${currentYear + 1} 00:00:00`);
};
// update the year element
const year = document.querySelector('.year');
year.innerHTML = getNewYear().getFullYear();
// select elements
const app = document.querySelector('.countdown-timer');
const message = document.querySelector('.message');
const heading = document.querySelector('h1');
const format = (t) => {
return t < 10 ? '0' + t : t;
};
const render = (time) => {
app.innerHTML = `
<div class="count-down">
<div class="timer">
<h2 class="days">${format(time.days)}</h2>
<small>Days</small>
</div>
<div class="timer">
<h2 class="hours">${format(time.hours)}</h2>
<small>Hours</small>
</div>
<div class="timer">
<h2 class="minutes">${format(time.minutes)}</h2>
<small>Minutes</small>
</div>
<div class="timer">
<h2 class="seconds">${format(time.seconds)}</h2>
<small>Seconds</small>
</div>
</div>
`;
};
const showMessage = () => {
message.innerHTML = `Happy New Year ${newYear}!`;
app.innerHTML = '';
heading.style.display = 'none';
};
const hideMessage = () => {
message.innerHTML = '';
heading.style.display = 'block';
};
const complete = () => {
showMessage();
// restart the countdown after showing the
// greeting message for a day ()
setTimeout(() => {
hideMessage();
countdownTimer.setExpiredDate(getNewYear());
}, 1000 * 60 * 60 * 24);
};
const countdownTimer = new CountDown(
getNewYear(),
render,
complete
);
Code language: JavaScript (javascript)
If you open the index.html
, you’ll see that the New Year countdown is up and running.
Sumary
In this tutorial, you’ve learned how to:
- Use the ES6 class to define a reusable countdown timer component.
- Use the
Date
object to manipulate time. - Use the setInterval() and clearInterval() to create and cancel a timed repeating action.