Weekly Dev Project #001— Digital Clock

Jakub Korch
Nerd For Tech
Published in
11 min readDec 3, 2023

This article is more or less transcript of my free YouTube series about making simple web development projects. If you prefer watching over reading, feel free to visit my channel “Dev Newbs”.

Hello, everyone! Welcome back to DewNewbs, the place where we explore the exciting world of web development. I’m J-Cup, and today, I’m thrilled to guide you through the process of creating something really cool — an animated digital clock using HTML, CSS, and JavaScript.

You might be wondering, ‘Why a digital clock?’ Well, aside from being a fun and visually appealing project, it’s a fantastic way to dive into the fundamentals of web development and get hands-on experience with these three essential technologies.

Whether you’re a beginner looking to enhance your skills or a seasoned developer searching for a creative project, you’re in the right place. By the end of this tutorial, you’ll not only have a sleek animated digital clock, but also a deeper understanding of how these (programming) languages work together to bring your ideas to life.

So, grab your favorite code editor, and let’s embark on this coding journey together. Without further ado, let’s jump right in and start building our animated digital clock!

Let’s start with HTML

We’ll kick things off by defining the basic structure.

<!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 001 - Digital Clock</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="digital-clock">
</div>
</body>

<script src="digitalClock.js" type="application/javascript"></script>
</html>

Here, we’ve set up a standard HTML5 document. The head section includes essential meta tags for character set, viewport settings, and compatibility. We’ve also linked an external stylesheet named ‘styles.css’ to handle the visual aspects of our digital clock.

Moving to the body, you’ll find a simple div element with the id ‘digital-clock’. This is where our clock will be dynamically generated and displayed.

Finally, towards the end of the document, just before the closing html tag, we’ve included a reference to an external JavaScript file named ‘digitalClock.js’. This file will contain the logic to make our digital clock tick.

Continue to CSS

Now that our HTML structure is in place, let’s move on to styling and animating our digital clock using CSS.

body {
width: 100vw;
height: 100vh;
overflow: hidden;
margin: 0;
padding: 0;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: #0e0e0e;
}

This part styles the body of the HTML document. It sets the width and height to 100% of the viewport width and height, respectively. The overflow: hidden; ensures that no scrollbars appear. Margin, padding, and border are removed (margin: 0; padding: 0; border: none;). The body is set to be a flex container, centering its content both horizontally and vertically. The background color is a dark shade

#digital-clock {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
}

This targets the element with the id digital-clock. It’s set as a flex container with center-aligned items in both directions. The flex-direction: row; ensures that the child elements are arranged horizontally.

.digit {
display: grid;
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
row-gap: 2px;
column-gap: 2px;
margin-right: 1vw;
}

Here, a class .digit is defined for the individual digits of the clock. It’s styled as a grid with 5 rows and 3 columns. Gaps between rows and columns are set, and a right margin is added for spacing.

.digit:nth-child(3n) > .cell:not(.active) {
background-color: transparent;
}

This rule targets inactive cells within every third digit and makes their background transparent.

.cell {
width: 2vw;
height: 2vw;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
transition: 0.25s all;
}

This styles the individual cells within each digit. They have a fixed width and height, are centered both horizontally and vertically, and have a border-box box model. A transition is added for smooth animations.

.active {
background-color: rgb(238, 216, 11);
transition: 0.25s all;
box-shadow: rgba(238, 216, 11, 0.5) 0px 0px 50px;
/*box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;*/
/*box-shadow: rgba(50, 50, 93, 0.25) 0px 50px 100px -20px, rgba(0, 0, 0, 0.3) 0px 30px 60px -30px, rgba(10, 37, 64, 0.35) 0px -2px 6px 0px inset;*/
/*box-shadow: rgba(238, 216, 11, 0.4) -5px 5px, rgba(238, 216, 11, 0.3) -10px 10px, rgba(238, 216, 11, 0.2) -15px 15px, rgba(238, 216, 11, 0.1) -20px 20px, rgba(240, 46, 170, 0.05) -25px 25px;*/
/*box-shadow: rgba(0, 0, 0, 0.4) 0px 2px 4px, rgba(0, 0, 0, 0.3) 0px 7px 13px -3px, rgba(0, 0, 0, 0.2) 0px -3px 0px inset;*/
/*box-shadow: rgba(238, 216, 11, 0.1) 0px 0px 0px 2px, rgba(238, 216, 11, 0.1) 0px 0px 0px 4px, rgba(238, 216, 11, 0.1) 0px 0px 0px 6px, rgba(238, 216, 11, 0.1) 0px 0px 0px 8px;*/
}

The .active class styles the active cells of the clock. It sets a background color and includes a transition for smooth changes. There’s also a box shadow effect with a yellowish color, providing a subtle highlight and shadow effect when a cell is active.

Note that there are additional commented-out box-shadow variations that you can experiment with.

This CSS code combines to create a visually appealing and animated digital clock. The flexibility of the grid layout and transitions allows for customization and experimentation.

Partial HTML

We need to check whether the HTML and CSS works together, so let’s create default state of digital clock manually…

<div id="digital-clock">
<div class="digit">
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
</div>
<div class="digit">
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
</div>
<div class="digit separator">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
<div class="digit">
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
</div>
<div class="digit">
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
</div>
<div class="digit separator">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
<div class="digit">
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
</div>
<div class="digit">
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
<div class="cell active"></div>
</div>
</div>

This long piece of HTML alongside the CSS we have so far, should give you something like this…

If you inspect the code with the developer tools, you will see that last digit has a margin just like every other digit. But this puts the whole clock slightly off center. Also the space between separators and digits is too wide for my taste. So let’s change that with the following CSS code…

.digit:nth-child(3n) {
margin-left: -1vw;
margin-right: 0vw;
}

.digit:last-child {
margin-right: 0vw;
}

Now it should look like this:

Subtle change, but change nonetheless. Let’s continue with the code.

Wrap up with JavaScript

So far everything looks good. It is time to start with the Javascript code and generate the initial structure of the digital clock dynamically.

First thing we need to do is to define the digits themselves. Every digit is displayed within a grid 3 columns wide and 5 rows high. Each value in a numbersMatrix represents the digit within this grid. One means the cell is active and should be visible, zero means the cell should be transparent / invisible. This will create the shape of a digit inside of a grid. Also the index at which the value is placed, represents the value of the digit itself. So the string with ones and zeros in the 0th index represents the zero digit and so on until digit nine at the index position 9.

let numbersMatrix = [
"111101101101111",
"010010010010010",
"111001111100111",
"111001111001111",
"101101111001001",
"111100111001111",
"111100111101111",
"111001001001001",
"111101111101111",
"111101111001111"
]

I placed the separator symbol separately from digits, because it logically does not belong to them.

let separator = "000010000010000"

To be able to insert elements into the HTML, we need a reference to an element with id “digital-clock”. So let’s make one.

const clockContainer = document.getElementById("digital-clock")

Now we need a loop to create digits and separators respectively. All in all, we will have 8 different symbols. 6 digits representing hours, minutes and seconds and two colon separators between them.

// create DIGITS 
for(let d = 0; d <= 7; d++){
// code here
}

We have to create a new HTML element each time and give it a class digit. Then we need to check whether we are creating a separator or digit. Separators have fixed positions at index 2 and 5, so we can use this information to our advantage.

// create DIGITS 
for(let d = 0; d <= 7; d++){
let digit = document.createElement("div")
digit.classList.add("digit")
}

We create a temporary variable which holds the symbol string representation from the variables defined sooner — remember numbersMatrix and separator variables.

// create DIGITS 
for(let d = 0; d <= 7; d++){
let digit = document.createElement("div")
digit.classList.add("digit")

let range

// if we create SEPARATOR
if(d == 2 || d == 5 ){
range = separator
digit.classList.add("separator")
}
// or create a digit
else {
range = numbersMatrix[0]
}

If we need to create a separator, we pass its reference to a variable, if not, we pass the first digit which is zero. Keep in mind, we are just creating the digital clock HTML structure, so it does not really matter which digit we use, but it makes best sense to use zero as it marks the initial value of a clock.

The next thing we need to do is to loop over each individual character (1 or 0) in the temporary variable that holds the symbol we want to create.

// create DIGITS 
for(let d = 0; d <= 7; d++){
...

for(c = 0; c < range.length; c++){
let cell = document.createElement("div")
range[c] == "1" ? cell.classList.add("cell", "active") : cell.classList.add("cell")
digit.appendChild(cell)
}
}

We create a div element with class cell and if the current value we iterate over equals 1 we additionally give it class active.

Then we append the newly created cell to the parent tag digit.

And after the loop we add the digit element to its parent clockContainer we defined at the beginning.

clockContainer.appendChild(digit)

This should be enough to create an initial HTML structure with zeros and separators just like we did manually, so let’s check our work now!

If you did not make any mistakes, you page should not change. Of course, to test it properly, you need to first remove manually written HTML code.

There is something we need to change with the digits of the clock. And that is a live reference to DIVs with class digits but not separators:

let digits = document.querySelectorAll(".digit:not(.separator)")

In order for the digital clock to update on a regular basis, we need to use one of the two functions. Either setTimeout, or setInterval. Since I do not want to recursively call setTimeout every time, I decided to go with the setInterval.

let digitalClock = setInterval(function(){
// your code here
}, 50)

We also need some variables to keep track of the current time fractions — namely hours, minutes and seconds, so let us create them.

let now = new Date()
let hours = now.getHours()
let minutes = now.getMinutes()
let seconds = now.getSeconds()

We also need to know the current timestamp, so let’s create also variable called now.

First thing to do inside of the interval function is to get the current timestamp into variable now. Then we take out fractions of time we are interested in (like hours, minutes and seconds) and check if the value needs to be updated. If any of the time fractions is changed, we create a new string containing new set of digits for our digital clock.

let digitalClock = setInterval(function(){
let now = new Date();

if(now.getHours() != hours || now.getMinutes() != minutes || now.getSeconds() != seconds){
hours = now.getHours()
minutes = now.getMinutes()
seconds = now.getSeconds()

const newDigits = ("0" + hours).slice(-2) + ("0" + minutes).slice(-2) + ("0" + seconds).slice(-2)

...
}
}, 50)

Then we parse through this new values one digit at a time and we update respective digit of the digital clock. Luckily we have only digits that need to be updated and reference to those digits from earlier.

...

for(let i=0; i < digits.length; i++){
let newDigit = newDigits[i]

...
}

Next we create reference to all the cell DIVs inside individual digit and we loop through them and give or take active class to them based on a digit value that needs to be displayed.

...

for(let i=0; i < digits.length; i++){
let newDigit = newDigits[i]
let cells = digits[i].querySelectorAll(".cell")

for(let x = 0; x < cells.length; x++){
if(numbersMatrix[newDigit][x] == "1"){
cells[x].classList.add("active")
}
else {
cells[x].classList.remove("active")
}
}
}

And that is it. Let’s refresh the page and see if it works…

If you would like to see the whole code in one place, feel free to check it in my public GitHub repository here:

https://github.com/j-cup/weekly-dev-project/tree/main/001-digital-clock

Thank you for joining me on the journey to create your own digital clock! I hope this tutorial has been interesting for you and you have learned something new.

If you enjoyed this tutorial, don’t forget to like, share, and subscribe for more exciting coding adventures. Feel free to experiment with the code, customize your digital clock, and make it truly yours.

Stay tuned for more engaging tutorials, and happy coding!

--

--

Jakub Korch
Nerd For Tech

Web enthusiast, programmer, husband and a father. Wannabe entrepreneur. You name it.