DEV Community

Cover image for Vanilla JavaScript countdown clock
Chris Bongers
Chris Bongers

Posted on • Originally published at daily-dev-tips.com

Vanilla JavaScript countdown clock

A time ago, we made this cool year loading bar, and this made me think a countdown timer would also be cool.

Since I'm getting married next year, let's use that as an example.

We will be creating an end date, and every second we will check how long away this is.

What you'll learn in this article:

  • ✅ Working with JavaScript dates
  • ✅ Calculating date differences
  • ✅ Converting milliseconds to readable formats
  • ✅ Styling our clock

The end result will look like this:

HTML Structure

Let's start by defining our HTML structure.

<div>
  <h1>The big day</h1>
  <p>Nicole & Chris wedding</p>
  <p id="done"></p>
  <ul>
    <li><span id="days">0</span> Days</li>
    <li><span id="hours">0</span> Hours</li>
    <li><span id="minutes">0</span> Minutes</li>
    <li><span id="seconds">0</span> Seconds</li>
  </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

We will have a title and intro paragraph, as well as a empty done div.
This done div will be used if the timer expired.

Then we have a list with days, hours, minutes, and seconds.
Default on 0 in case the date expired.

Adding some CSS for styling

Now ofcourse we want this too look a bit nicer.

body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  font-family: Roboto, "Helvetica Neue", Arial, sans-serif;
  text-align: center;
  margin: 0;
  padding: 0;
  background: #8fbfe0;
}
h1 {
  font-size: 3rem;
  margin-top: 0;
}
ul {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  margin-top: 2rem;
}
ul li {
  background: #7c77b9;
  border-radius: 10px;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  margin: 0 0.5rem;
  color: #8fbfe0;
  box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.5);
}
ul li span {
  font-size: 2rem;
}
Enter fullscreen mode Exit fullscreen mode

What you'll see is that we remove the main styling from the ul to use Flexbox to center it, and space the elements.
Then we add a box-shadow and some colors to make it pop more.

JavaScript countdown timer

Now the JavaScript part.

Let's first define our end date:

const end = new Date("May 03, 2021 00:00:00").getTime();
Enter fullscreen mode Exit fullscreen mode

We define the date as a Date object and use the getTime function to get the milliseconds. We do this because it's easier to count with.

Now let's get all our output span elements.

const dayEl = document.getElementById('days');
const hoursEl = document.getElementById('hours');
const minutesEl = document.getElementById('minutes');
const secondsEl = document.getElementById('seconds');
Enter fullscreen mode Exit fullscreen mode

The last set of variables we can define to make it easier for ourselves are the time fragment pieces.

const seconds = 1000;
const minutes = seconds * 60;
const hours = minutes * 60;
const days = hours * 24;
Enter fullscreen mode Exit fullscreen mode

What this means:

  • 1000 seconds = 1 millisecond so if we do (time / 1000) we get our seconds
  • (seconds * 60) = 1 minute (60.000 milliseconds)
  • (minutes * 60) = 1 hour, because 1 hour has 60 seconds.
  • (hours * 24) = 1 day, because 1 day has 24 hours

Now we will need to create a setInterval function to run every second.

const x = setInterval(function () {
    // Code here
}, seconds);
Enter fullscreen mode Exit fullscreen mode

We attach it to a const to be able to unset it if it's no longer needed.

Now, let's get the current timestamp and a difference between our end date and now.

let now = new Date().getTime();
const difference = end - now;
Enter fullscreen mode Exit fullscreen mode

The difference will now have the difference in milliseconds between now and our set date.

Let's first check if it's not already expired.

if (difference < 0) {
    clearInterval(x);
    document.getElementById("done").innerHTML = "We're married! 🎉";
    return;
}
Enter fullscreen mode Exit fullscreen mode

Here, we check if the difference is smaller then 0, then we clear our interval so it won't run again.
We also use a return to stop the rest of the function from running.

Now all that's left is to show the correct numbers for each element.

dayEl.innerText = Math.floor(difference / days);
hoursEl.innerText = Math.floor( (difference % days) / hours );
minutesEl.innerText = Math.floor( (difference % hours) / minutes );
secondsEl.innerText = Math.floor( (difference % minutes) / seconds );  
Enter fullscreen mode Exit fullscreen mode

As mentioned in our example we return a floored value of the difference converted to each respectable element.

Note the use of the % is to get a remained back.

For example, let's say our difference in milliseconds is 15091810828.

  • Days: (15091810828 / 86400000) = 174
  • Hours: (15091810828 % 86400000) = 58210828 => (58210828 / 3600000) = 16
  • Minutes: (15091810828 % 3600000) = 610828 => (610828 / 60000) = 10
  • Seconds: (15091810828 % 60000) = 10828 => (10828 / 1000) = 10

This might be a bit much. I'd advise you to even write down one number and calculate it on paper to get a good feel for what's happening.

There we go, we now have a countdown timer in JavaScript, let me know what you create with this cool piece of code.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Top comments (2)

Collapse
 
krhoyt profile image
Kevin Hoyt

First and foremost, congratulations on your engagement! Second, thanks for the post. Maybe it was the occasion, or maybe it was that the content dealt with time (a concept - illusion? - that fascinates me), but I could not help wondering what this might look like as a web component. Third then, is that I reworked it as a web component.

Gist: gist.github.com/krhoyt/4fdb6feb68c...
Demo: temp.kevinhoyt.com/countdown/

I did move from setInterval() to requestAnimationFrame(). I do not know that it adds anything to this specific implementation. Personal preference I suppose. I also made custom style properties available from outside the component. The component also has a couple properties that control some aspects of styling.

Thanks for the inspiration!

Collapse
 
dailydevtips1 profile image
Chris Bongers

Hey Kevin,

Thanks for the congrats, and this awesome web component, looks amazing, really nice work on this!