Howdy Folks, Welcome to this new tutorial. In this tutorial, you will learn how to make a realtime analog clock using HTML, CSS, and Javascript.

Before jumping right in first, take a look at the finished product here at Codepen --> https://codepen.io/thecodingpie/pen/yLezdKG

You can download the completed project from GitHub --> https://github.com/the-coding-pie/Analog-Clock-Javascript

Prerequisites

I assume that you had a decent understanding of HTML, CSS, and Javascript.

I am going to use visual studio code as my text editor. You are free to use whatever code editor you like. And finally, make sure you have installed Live Server by Ritwick Dey in visual studio code. If you don't have Live Server installed, then:

  • Open visual studio code
  • Goto Extensions tab (Ctrl + Shift + X)
  • Search for "Live Server" by Ritwick Dey
  • Then Install it

Breaking Down the Logic

The logic is quite simple. It's not as complex as you think. We are going to rotate our hands of the clock by just tweaking a single property called transform: rotate(). That's it. There is no complex animation or things like that. With that being said, let's get started.

Initial Setups

This is my folder structure:

folder structure of project

  • First, create the root folder that holds everything and name it as "Analog Clock".
  • Then open this root folder inside visual studio code.
  • Then directly inside that root folder, create a file named "index.html" --> This holds our HTML.
  • Then again directly inside our root folder, create three folders:
    • One named "css" --> Inside this folder, create a file named "styles.css"
    • Second folder named "js" --> Inside this folder, create a file named "script.js"
    • Then another folder named "img" --> Download this image and put it inside this folder.

That's it. Now you should have a folder structure similar to above. From here on I will be doing everything bit by bit so that you can get a better understanding of what we are doing... Now the HTML part...

HTML

Open the "index.html" file and type the following:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" type="text/css" href="css/styles.css">
  <title>Analog Clock</title>
</head>

<body>
  

  <script type="text/javascript" src="js/script.js"></script>
</body>

</html>

That's our boilerplate code. There's nothing special in there. We are giving some <meta> tags, one for setting the charset, and one for the viewport. They are not required here. But always using them is a good practice. Then we are linking our "styles.css" file. Then set the title. Before the ending </body> tag, we are linking our "script.js" file. That's it.

Now type the following code between <body> and opening <script> tag.

 <div class="clock">

    <div class="hand hour"></div>
    <div class="hand minute"></div>
    <div class="hand second"></div>

 </div>

The outer <div> with a class="clock" is for the clock's body. Inside that, we had 3 <div>. Each <div> has a common class name of "hand" and a unique class name for each namely hour, minute, and second. The "hand" class is for applying some common styling for all the hands. 

The final code for "index.html" looks like below:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" type="text/css" href="css/styles.css">
  <title>Analog Clock</title>
</head>

<body>

  <div class="clock">
    <div class="hand hour"></div>
    <div class="hand minute"></div>
    <div class="hand second"></div>
  </div>

  <script type="text/javascript" src="js/script.js"></script>
</body>

</html>

Open it with Live Server by right-clicking on the "index.html" file (inside visual studio code), then scroll down and click on the "Open with Live Server" option and take a look at it at the browser. You can't see anything now. Because we only linked the "styles.css" file but didn't write any CSS styles. So now let's do that. Let's add some styles...

CSS

Open the "styles.css" file you created and type the following:

body {
  min-width: 100vw;
  min-height: 100vh;
  overflow: hidden;
  background-color: #2948ff;
  display: flex;
  justify-content: center;
  align-items: center;
}
  • min-width: 100vw and min-height: 100vh makes the body fill the viewport(screen).
  • overflow: hidden takes away the scrollbar if it is visible.
  • Then we are giving a background-color of #2948ff, a kind of nice blue.
  • display: flex, justify-content: center, and align-items: center all makes the clock center.

Now below the above code type the following:

/* clock */

.clock {
  width: 300px;
  height: 300px;
  background-color: #73ff00;
  border-radius: 50%;
  border: 8px solid #000;
  box-shadow: 2px 2px 8px 2px rgba(22, 45, 75, 0.92);
  background-image: url('../img/face.png');
  background-size: cover;
  position: relative;
}

/* clock style ends */

We are selecting the <div> with the class="clock" and:

  • Setting the width: 300px and height: 300px
  • Give a background-color: #73ff00, a light green color
  • border-radius: 50%, makes the clocks <div> round.
  • border: 8px solid #000 gives a solid black(#000) border of 8px.
  • box-shadow gives a shadow to the clocks <div>. This is the order --> box-shadow: offset-x offset-y blur spread-radius color
  • Then set the clocks face image you downloaded as background-image.
  • background-size: cover helps to cover the <div> with the background-image.
  • Then we are setting position: relative. Because we are going to absolutely position everything relative to our clock <div>. All the hands and other stuff. So this line is important.

The following code is for the black round at the clock's center. Type it below the previous code:

/* round center */

.clock::before {
  content: '';
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background-color: #000;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 999;
}

/* round center style ends */

Here we are creating the black round at the clock's center using "::before" pseudo-selector.

  • content: '' --> without this style, nothing will show off.
  • width: 15px and height: 15px sets the width and height.
  • border-radius: 50% makes it round.
  • background-color: #000 makes it black.
  • position: absolute, top: 50%, left: 50%, and transform: translate(-50%, -50%) makes it center relative to clock <div>.
  • z-index: 999 gives a higher priority along the z-axis.

Copy the following code below the above code:

/* common style for every hand */

.hand {
  /* apply the width */
  /* apply the height */
  /* apply the background-color */
  position: absolute;
  bottom: 50%;
  left: 50%;
  transform: translateX(-50%) rotate(90deg);
  transform-origin: bottom;
  border-top-left-radius: 7px;
  border-top-right-radius: 7px;
}

/* common style ends */

We are applying some styles common to all hands.

If you give width:10px,  height:30%, and background-color: #000 to .hand, then you can see what's happening. Later make sure you deleted the widthheight, and background-color property.

  • position: absolute makes its position absolute to the clock <div>
  • Then push it from the bottom: 50% and left: 50%
  • Then transform: translateX(-50%) rotate(90deg) makes it dead center and rotate it 90deg. We are going to tweak this rotate() property to rotate the hands. Here I applied 90deg just to know if the rotation works or not.
  • transform-origin: bottom sets the axis of the hands to bottom. So it can stick to the center of the .clock and rotate in 360 degrees.
  • The last two lines are pretty self-explanatory. They give a border-radius: 7px to top-left and top-right of hands.

Now the styles for each hand. Copy them below the previous code:

/* hour hand */

.hour {
  width: 8px;
  height: 28%;
  background-color: #000;
}

/* hour hand style ends */
/* minute hand style */

.minute {
  width: 5px;
  height: 38%;
  background-color: #000;
}

/* minute hand style ends */
/* second hand style */

.second {
  width: 3px;
  height: 40%;
  background-color: #ff0000;
}

/* second-hand style ends */

These styles are pretty self-explanatory. I hope you can easily understand it. Just go through it.

This is the final code for "styles.css". Make sure the code you typed up to this point inside "styles.css" is exactly like the below:

body {
  min-width: 100vw;
  min-height: 100vh;
  overflow: hidden;
  background-color: #2948ff;
  display: flex;
  justify-content: center;
  align-items: center;
}

/* clock */

.clock {
  width: 300px;
  height: 300px;
  background-color: #73ff00;
  border-radius: 50%;
  border: 8px solid #000;
  box-shadow: 2px 2px 8px 2px rgba(22, 45, 75, 0.92);
  background-image: url('../img/face.png');
  background-size: cover;
  position: relative;
}

/* clock style ends */

/* round center */

.clock::before {
  content: '';
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background-color: #000;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 999;
}

/* round center style ends */

/* common style for every hand */

.hand {
  position: absolute;
  bottom: 50%;
  left: 50%;
  transform: translateX(-50%) rotate(90deg);
  transform-origin: bottom;
  border-top-left-radius: 7px;
  border-top-right-radius: 7px;
}

/* common style ends */

/* hour hand */

.hour {
  width: 8px;
  height: 28%;
  background-color: #000;
}

/* hour hand style ends */
/* minute hand style */

.minute {
  width: 5px;
  height: 38%;
  background-color: #000;
}

/* minute hand style ends */
/* second hand style */

.second {
  width: 3px;
  height: 40%;
  background-color: #ff0000;
}

/* second hand style ends */

Now the Javascript part...

Javascript

Open the "script.js" file and type the following:

// grab a reference of every hands

// hour hand
let hourHand = document.querySelector('.hour');
// minute hand 
let minuteHand = document.querySelector('.minute');
// second hand
let secondHand = document.querySelector('.second');

Here we are just grabbing the <div class="hand hour">, <div class="hand minute"> and <div class="hand second"> and storing its reference inside proper variables namely hourHand, minuteHand and secondHand.

Now we had the reference of the three hand <div>. Let's make the function called rotate(). Type the following code below the above code:

// function that rotates the hands
function rotate() {
  
}

Type the following inside the function rotate():


  // get the current Date object from which we can obtain the current hour, minute and second
  const currentDate = new Date();

  // get the hours, minutes and seconds
  const hours = currentDate.getHours();
  const minutes = currentDate.getMinutes();
  const seconds = currentDate.getSeconds();

Make sure you typed them inside function rotate(). To make the clock show the current time, we need to get the current time right? That's what we are doing here:

  • new Date() creates an instance of the Date class from which we can get all kinds of things like current date, hours, minutes, seconds, etc. Then we are storing that instance(object) inside currentDate constant.
  • Then we are fetching the current hours using getHours() method, current minutes using getMinutes() and current seconds using getSeconds(). And we are storing them inside corresponding constants namely hours, minutes, and seconds.

But how we are going to rotate each hand. By how much value?. By how much degree? We need to calculate them. That's our next task. Type the following inside function rotate():

 // rotating fraction --> how many fraction to rotate for each hand.
  const secondsFraction = seconds / 60;
  const minutesFraction = (secondsFraction + minutes) / 60;
  const hoursFraction = (minutesFraction + hours) / 12;

  // actual deg to rotate
  const secondsRotate = secondsFraction * 360;
  const minutesRotate = minutesFraction * 360;
  const hoursRotate = hoursFraction * 360;
  • Dividing current seconds by 60 gives the fraction of the second. Then store it inside secondsFraction. We divide by 60 because there are 60 seconds in a minute.
  • To get the minutesFraction, first, add secondsFraction to minutes then divide it by 60. 
  • To get hoursFraction, add minutesFraction to hours then divide it by 12.

I will explain the logic behind why we need to add secondsFraction to minutes and minutesFraction to hours instead of directly dividing them in a bit. So don't worry about them for now.

  • Then we are multiplying each fraction with 360 to get the actual degree to rotate for each hand. (Why 360? Because 360 degree makes the circle).

Here is the explanation behind the addition:

We should have done something like below (you don't have to copy the code below):

// rotating fraction --> how many fraction to rotate for each hand.
  const secondsFraction = seconds / 60;
  const minutesFraction = minutes / 60;
  const hoursFraction = hours / 12;


But there is a small pitfall here. If we do it like this, our second hand will rotate fine. It will rotate 60 times a minute around the clock.

But our minute hand will also do the same. It will rotate 60 times for each hour.  And our hour hand too. Our hour hand will rotate exactly 12 times. It will jump from one digit to another digit. 

But that's not how real-world clocks move. If you take a look at them, the hour hand and the minute hand doesn't exactly jump from one digit to another digit suddenly. They will move gradually. So to slow them down and make our hour hand and minute hand move gradually, we need to do something.

For that reason why we did the addition (to slow down the hands in relation to each other hands).

Now apply the calculated rotation value to each hand element. Type the following inside function rotate():

// apply the rotate style to each element
  // use backtick `` instead of single quotes ''
  secondHand.style.transform = `rotate(${secondsRotate}deg)`;
  minuteHand.style.transform = `rotate(${minutesRotate}deg)`;
  hourHand.style.transform = `rotate(${hoursRotate}deg)`;

Here we are applying the calculated rotation values to the transform: rotate() property. We are using the backticks `` instead of quotation marks '' to make template literals. You can read about template literals from here --> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

Template literals can contain placeholders(${}). That's the main reason why we are using them. Inside the placeholder, we are putting the corresponding constants like secondsRotate, minutesRotate, hoursRotate where each holds the corresponding degree values to rotate. The placeholder will later replace them with the corresponding values of the constants.

That's it, our function rotate() is complete. We need to call this rotate() function every 1 second (1000 milliseconds). For that add the following code below the function rotate():

// for every 1000 milliseconds(ie, 1 second) interval, activate the rotate() function.
setInterval(rotate, 1000);

That's it. Now our clock will work exactly as we expected :)

This is the final code for the "script.js" file. Make sure the code you typed up to this point inside "script.js" is exactly like the below:

// grab a reference of every hands

// hour hand
let hourHand = document.querySelector('.hour');
// minute hand 
let minuteHand = document.querySelector('.minute');
// second hand
let secondHand = document.querySelector('.second');

// function that rotates the hands
function rotate() {
  // get the current Date object from which we can obtain the current hour, minute and second
  const currentDate = new Date();

  // get the hours, minutes and seconds
  const hours = currentDate.getHours();
  const minutes = currentDate.getMinutes();
  const seconds = currentDate.getSeconds();

  // rotating fraction --> how many fraction to rotate for each hand.
  const secondsFraction = seconds / 60;
  const minutesFraction = (secondsFraction + minutes) / 60;
  const hoursFraction = (minutesFraction + hours) / 12;

  // actual deg to rotate
  const secondsRotate = secondsFraction * 360;
  const minutesRotate = minutesFraction * 360;
  const hoursRotate = hoursFraction * 360;

  // apply the rotate style to each element
  // use backtick `` instead of single quotes ''
  secondHand.style.transform = `rotate(${secondsRotate}deg)`;
  minuteHand.style.transform = `rotate(${minutesRotate}deg)`;
  hourHand.style.transform = `rotate(${hoursRotate}deg)`;
}

// for every 1000 milliseconds(ie, 1 second) interval, activate the rotate() function.
setInterval(rotate, 1000);

Conclusion

I hope you enjoyed this tutorial. If you had any doubts, then please comment them below. And if you enjoyed this tutorial, then please hit the like button below. Thank you ;)