CyberCodeLab logo — neon green lab flask with terminal symbolCyberCodeLab
Neon green digital clock display built with JavaScript Date object and setInterval — beginner coding project

web-development · Basic · 2026-07-05

Project: Build a Digital Clock with HTML, CSS & JavaScript

A beginner-friendly project tutorial — build a live digital clock from scratch and learn setInterval, the Date object and template literals along the way.

Projects are the fastest way to make knowledge stick. This one is small enough to finish in fifteen minutes, but it teaches four concepts you will use in almost every JavaScript app.

What you will learn

  1. The Date object — reading the current time
  2. setInterval — running code repeatedly
  3. padStart — formatting numbers like 07 instead of 7
  4. Template literals — building strings the modern way

Step 1: the HTML skeleton

We need very little markup — a box, a heading for the time, and a paragraph for the date:

<div class="clock-box">
  <h1 id="clock">--:--:--</h1>
  <p id="date"></p>
</div>

The --:--:-- placeholder shows until JavaScript takes over.

Step 2: reading the time

JavaScript's built-in Date object knows the current date and time:

const now = new Date();
now.getHours();    // 0–23
now.getMinutes();  // 0–59
now.getSeconds();  // 0–59
now.toDateString(); // "Sat Jul 05 2026"

Step 3: formatting with padStart

getMinutes() returns 7, not 07 — which would make the clock jump around. padStart(2, "0") fixes that by padding the string to two characters:

String(7).padStart(2, "0");   // "07"
String(12).padStart(2, "0");  // "12"

Step 4: template literals

Instead of gluing strings with +, modern JavaScript uses backticks and ${}:

const time = `${h}:${m}:${s}`;   // "14:07:33"

Step 5: making it tick

setInterval(fn, ms) runs a function every ms milliseconds. One second = 1000 ms:

updateClock();                    // run once immediately
setInterval(updateClock, 1000);   // then every second

Calling updateClock() once before the interval matters — without it, the page shows the placeholder for a full second before the first update.

Try it yourself

The complete working clock is in the editor below. Try these challenges:

  1. Add a blinking colon by toggling its opacity on every tick.
  2. Show the time in 12-hour format with an AM/PM label (hint: h % 12).
  3. Display your city name under the date.
  4. Bonus: change the border colour every second using Math.random() and style.borderColor.

Press Run after each change to see the result instantly.

Practice exercises

Three extensions to the working clock, each one step harder.

Exercise 1 (easy): Add a greeting under the date that changes with the time of day: "Good morning" before 12, "Good afternoon" before 18, "Good evening" after. Add a <p id="greeting"> in the HTML and set it inside updateClock().

Solution:

const hour = now.getHours();
const greeting = hour < 12 ? "Good morning" : hour < 18 ? "Good afternoon" : "Good evening";
document.getElementById("greeting").textContent = greeting;

Exercise 2 (medium): Show the weekday name in your own language above the time. toLocaleDateString accepts a locale and options — try "ur-PK" or "en-GB" with { weekday: "long" }.

Solution:

document.getElementById("date").textContent =
  now.toLocaleDateString("en-GB", { weekday: "long", day: "numeric", month: "long", year: "numeric" });

Exercise 3 (challenge): Add a "time until midnight" line — hours and minutes remaining today. Build a Date for the next midnight, subtract now from it, and convert the milliseconds. (This is the core of every countdown timer.)

Solution:

const midnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
const msLeft = midnight - now;
const hLeft = Math.floor(msLeft / 3600000);
const mLeft = Math.floor((msLeft % 3600000) / 60000);
document.getElementById("countdown").textContent =
  hLeft + "h " + mLeft + "m until midnight";

Practise what you learned

Edit the code below and press Run to see your changes live.

practice-editor
preview — press Run to refresh

Test yourself

Answer from memory first, then check yourself against the answer.

Q1Why do we call updateClock() once before starting setInterval?

setInterval waits one full interval before its first run, so without the direct call the page would show the --:--:-- placeholder for a whole second. Calling it once immediately paints the correct time from the very first frame.

Q2What does padStart(2, '0') fix in the clock?

getMinutes() returns 7, not 07 — single digits would make the clock's width jump around every few seconds. padStart pads the string to two characters with a leading zero, keeping the display stable.

Q3What is the difference between setInterval and setTimeout?

setTimeout runs a function once after a delay; setInterval runs it repeatedly at every interval. A clock needs setInterval — though you could build one from setTimeout by re-scheduling inside the callback.