Analog Clock using HTML, CSS and JavaScript

Analog Clock using HTML, CSS and JavaScript

In today's digital world, analog clocks may look like a thing of the past, however, they still hold some unique charm! It doesn't matter if you just want to practice your coding skills or simply want to add a beautiful analog clock to your website and provide a practical way to display time. In this tutorial we will explore how to create an analog clock using HTML, CSS, and JavaScript, so without any further ado, let's start to code it!

Step 1: Setting up HTML code for analog clock

As always we will start from an empty file, so let's generate a boilerplate (if you are using a Visual Studio Code you can do so just by writing "!" in the index.html file). Quick change of the title, linking a style.css file in the head section. At the bottom of the body element, we will put a script tag that will point to a main.js file.

<!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" />
    <link rel="stylesheet" href="style.css" />
    <title>Analog Clock using HTML CSS and JavaScript</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>

Now we have to create an analog clock itself, so at first we will create a 'clock' div - it will be used as a clock's face and a container for hands and markings. If it comes to the clock's hands, we will create three divs, one for the hour hand, a second for minutes, and a third for seconds. We will have two types of markings, one will be used for main hours marks (3, 6, 9, and 12), while the second one with the name 'marking-alt' will be used for the rest - those markings will have a different color and will be slightly shorter than main markings. All of our markings will be placed inside of the div called 'marking', which works as a container for each marking, so we will be able to place it easily on the clock face.

<div class="clock">
  <div class="hand hand-hours"></div>
  <div class="hand hand-minutes"></div>
  <div class="hand hand-seconds"></div>

  <div class="marking marking-1">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-2">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-3">
    <div class="marking-main"></div>
  </div>
  <div class="marking marking-4">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-5">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-6">
    <div class="marking-main"></div>
  </div>
  <div class="marking marking-7">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-8">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-9">
    <div class="marking-main"></div>
  </div>
  <div class="marking marking-10">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-11">
    <div class="marking-alt"></div>
  </div>
  <div class="marking marking-12">
    <div class="marking-main"></div>
  </div>
</div>

Here is the HTML code for analog clock which you should place inside your index.html file:

<!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" />
    <link rel="stylesheet" href="style.css" />
    <title>Analog Clock using HTML CSS and JavaScript</title>
  </head>
  <body>
    <div class="clock">
      <div class="hand hand-hours"></div>
      <div class="hand hand-minutes"></div>
      <div class="hand hand-seconds"></div>

      <div class="marking marking-1">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-2">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-3">
        <div class="marking-main"></div>
      </div>
      <div class="marking marking-4">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-5">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-6">
        <div class="marking-main"></div>
      </div>
      <div class="marking marking-7">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-8">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-9">
        <div class="marking-main"></div>
      </div>
      <div class="marking marking-10">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-11">
        <div class="marking-alt"></div>
      </div>
      <div class="marking marking-12">
        <div class="marking-main"></div>
      </div>
    </div>
    <script src="main.js"></script>
  </body>
</html>

Step 2: Styling the analog clock with CSS

Now it's time to jump into CSS and have some fun with it. We will start with basic stuff, we are going to reset padding and margin plus change box-sizing to border-box. Next, we will style the body - let's slightly change the background color and center everything using Grid.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background: #fbfef9;
  height: 100vh;
  display: grid;
  place-content: center;
}

If it comes to styling the clock itself we will have a height and width of 450 pixels, change its background to #191923 (it's a really nice shade of black color), and to make it round we will set up a border-radius up to 50%. We will also add some nice borders and outer/inner box shadows to make it slightly prettier. Finally, we will change the position of this element to relative, so we will easily place all the marks and hands inside of it.

.clock {
  background: #191923;
  width: 450px;
  height: 450px;
  border-radius: 50%;
  border: 0.75rem solid #44444f;
  box-shadow: 0 0 16px 0 #2b2c46, inset 4px 4px 16px 0 rgba(90, 86, 102, 0.4),
    inset -4px -4px 16px 0 rgba(90, 86, 102, 0.4);
  position: relative;
}

Our analog clock will have a nice center pin, we are going to create it by adding an after pseudoelement to a clock class. Of course, we have to use position absolute (absolute to the clock element), and to actually appear on the screen we have to add the empty value of content to it. To make it show above hands we will change the z-index to 10. We will also make it round by changing border-radius to 50% and set up a width/height to 18px. Finally, to position it in the center we will use top and left properties, we want to set them up to 50%, so our pin will be placed in the middle of the clock - well, the top left border will be in the center. To fix it we will use transform: translate(-50%, -50%) - it will move the pin 50% of the element width (in our example it's 9px) to the left and top, placing it perfectly in the center.

.clock::after {
  position: absolute;
  z-index: 10;
  content: "";
  background: #aaa9bc;
  border-radius: 50%;
  width: 18px;
  height: 18px;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Now let's work on hands, we have a class called hand and it's shared by all three hands, so let's work on it first. To place it properly in the clock we will use a position absolute as well as z-index, however, to show our hands below the center pin we will set up the value to 5. We will also place our hands in the center by using bottom and left properties, but, we will only reposition them on the X-axis to put them perfectly in the center. We will also add a small border-radius to the top left and top right edges of the hands just to make them a bit more elegant. Since our clock's hands will rotate we want to change the starting point of the animation from the default one to the bottom of the hand - thanks to this our analog clock will work as the real clock. The last part of styling this element is the rotation, we will add a custom property called rotation, we can do so by adding '--' before the property name, we will, of course, set the value to 0, but this is only the starting position which will be changed by using JavaScript. To actually use the rotation property we just added we are going to use the transform: rotate property, where we will simply calculate rotation by multiplying our newly added property with 1 deg - it will simply convert the value to degrees.

.clock .hand {
  position: absolute;
  z-index: 5;
  bottom: 50%;
  left: 50%;
  border-radius: 5px 5px 0 0;
  transform-origin: bottom;
  --rotation: 0;
  transform: translateX(-50%) rotate(calc(var(--rotation) * 1deg));
}

Styling separate hands is pretty easy, we will only set up their background colors, width, and height as we want - personally, I used #44444f for both hours and minutes hands and #cea716 for seconds, but naturally, you can pick any other color you want.

.clock .hand-hours {
  width: 12px;
  height: 22%;
  background: #44444f;
}

.clock .hand-minutes {
  width: 8px;
  height: 35%;
  background: #44444f;
}

.clock .hand-seconds {
  width: 4px;
  height: 45%;
  background: #cea716;
}

We are almost done with styling the analog clock with CSS, now we will focus on markings - at first, we will style a shared class. As with any other element that is inside of the clock we will change position to absolute, set a width and height to 100%, and small padding from the border - it will look way better this way.

.clock .marking {
  position: absolute;
  width: 100%;
  height: 100%;
  padding-top: 1.25rem;
}

Since we have two types of markings - main and alt one, both of them will be centered using margin: auto and have a width of 4 pixels, however, the main one is going to be slightly bigger and will have a different color. I will use 40 pixels for height and #7988f3 as the background color, but our alt marking is going to be only 20 pixels high and use #f8f8ff color.

.marking-main {
  margin: auto;
  width: 4px;
  height: 40px;
  background: #7988f3;
}

.marking-alt {
  margin: auto;
  width: 4px;
  height: 20px;
  background: #f8f8ff;
}

Finally, we will rotate each marking for 30 degrees more, so marking-1 will rotate for 30 degrees, marking-2 for 60 degrees and marking-3 for 90 degrees, and so on towards marking-11, which will be rotated for 330 degrees. We won't rotate the twelfth marking tho, we simply don't need to do so, since it is placed in the starting position.

.clock .marking-1 {
  transform: rotate(30deg);
}

.clock .marking-2 {
  transform: rotate(60deg);
}

.clock .marking-3 {
  transform: rotate(90deg);
}

.clock .marking-4 {
  transform: rotate(120deg);
}

.clock .marking-5 {
  transform: rotate(150deg);
}

.clock .marking-6 {
  transform: rotate(180deg);
}

.clock .marking-7 {
  transform: rotate(210deg);
}

.clock .marking-8 {
  transform: rotate(240deg);
}

.clock .marking-9 {
  transform: rotate(270deg);
}

.clock .marking-10 {
  transform: rotate(300deg);
}

.clock .marking-11 {
  transform: rotate(330deg);
}

Check out the full CSS code for analog clock, simply paste it into the style.css and let's work on JavaScript!

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background: #fbfef9;
  height: 100vh;
  display: grid;
  place-content: center;
}

.clock {
  background: #191923;
  width: 450px;
  height: 450px;
  border-radius: 50%;
  border: 0.75rem solid #44444f;
  box-shadow: 0 0 16px 0 #2b2c46, inset 4px 4px 16px 0 rgba(90, 86, 102, 0.4),
    inset -4px -4px 16px 0 rgba(90, 86, 102, 0.4);
  position: relative;
}

.clock::after {
  position: absolute;
  z-index: 10;
  content: "";
  background: #aaa9bc;
  border-radius: 50%;
  width: 18px;
  height: 18px;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.clock .hand {
  position: absolute;
  z-index: 5;
  bottom: 50%;
  left: 50%;
  border-radius: 5px 5px 0 0;
  transform-origin: bottom;
  --rotation: 0;
  transform: translateX(-50%) rotate(calc(var(--rotation) * 1deg));
}

.clock .hand-hours {
  width: 12px;
  height: 22%;
  background: #44444f;
}

.clock .hand-minutes {
  width: 8px;
  height: 35%;
  background: #44444f;
}

.clock .hand-seconds {
  width: 4px;
  height: 45%;
  background: #cea716;
}

.clock .marking {
  position: absolute;
  width: 100%;
  height: 100%;
  padding-top: 1.25rem;
}

.marking-main {
  margin: auto;
  width: 4px;
  height: 40px;
  background: #7988f3;
}

.marking-alt {
  margin: auto;
  width: 4px;
  height: 20px;
  background: #f8f8ff;
}

.clock .marking-1 {
  transform: rotate(30deg);
}

.clock .marking-2 {
  transform: rotate(60deg);
}

.clock .marking-3 {
  transform: rotate(90deg);
}

.clock .marking-4 {
  transform: rotate(120deg);
}

.clock .marking-5 {
  transform: rotate(150deg);
}

.clock .marking-6 {
  transform: rotate(180deg);
}

.clock .marking-7 {
  transform: rotate(210deg);
}

.clock .marking-8 {
  transform: rotate(240deg);
}

.clock .marking-9 {
  transform: rotate(270deg);
}

.clock .marking-10 {
  transform: rotate(300deg);
}

.clock .marking-11 {
  transform: rotate(330deg);
}

Step 3: Writing JavaScript code for analog clock

We are almost done! In our JavaScript file, we are going to start by getting the clock's hands - we will use document.querySelector for that purpose and save each one as hoursHand, minutesHand, and secondsHand.

const hoursHand = document.querySelector(".hand-hours");
const minutesHand = document.querySelector(".hand-minutes");
const secondsHand = document.querySelector(".hand-seconds");

Next, we will set up an arrow function called setTime. Inside it we will get the current date using the new Date() constructor - we are easily going to get the current time from it, so we will store it using the currentTime variable. From it we are going to get seconds and divide them by 60, since there are 60 seconds on our analog clock - this will give us the information on how far we should rotate our second hand, we will store it in the secondsRation variable. A similar story goes for minutes and hours (we will divide hours by 12 tho since we got only 12 hours on the analog clock), but there is one problem - this would let our hands move only when the minute or hour passes, and, clocks don't really work this way, since they gradually move each second. To fix this issue we will add our secondsRatio to the minutes and the result of it will be divided by 60 - the result of this calculation will be stored as a minutesRatio and then added to hours.

const setTime = () => {
  const currentTime = new Date();
  const secondsRatio = currentTime.getSeconds() / 60;
  const minutesRatio = (secondsRatio + currentTime.getMinutes()) / 60;
  const hoursRatio = (minutesRatio + currentTime.getHours()) / 12;
};

As we have those data we just have to use them with the clock's hands and a custom property called rotation we have set up in the style.css earlier. Our secondsRatio / minutesRatio / handsRatio has to be multiplied by 360 degrees, since well, the circle has 360 degrees (let's say we have 30 seconds, that's 0.5 of the full clock rotation, now we do some math: 360 degrees * 0.5 of the rotation and we get 180 degrees, that's how far we should rotate our hand in degrees).

const setTime = () => {
  const currentTime = new Date();
  const secondsRatio = currentTime.getSeconds() / 60;
  const minutesRatio = (secondsRatio + currentTime.getMinutes()) / 60;
  const hoursRatio = (minutesRatio + currentTime.getHours()) / 12;

  secondsHand.style.setProperty("--rotation", secondsRatio * 360);
  minutesHand.style.setProperty("--rotation", minutesRatio * 360);
  hoursHand.style.setProperty("--rotation", hoursRatio * 360);
};

Once we are all done we have to make the analog clock tick, therefore, we will use the setInterval() method, which will call our setTime function every 1000 milliseconds (which is simply one second).

setInterval(setTime, 1000);

There is one small problem left, once you open the page you will see hands in the default position for one second before they go into the proper position and show the current time - we will fix it by simply calling the setTime function at the bottom of our JavaScript file.

setTime();

Below you can find the final JavaScript code for analog clock, copy and paste it into main.js file:

const hoursHand = document.querySelector(".hand-hours");
const minutesHand = document.querySelector(".hand-minutes");
const secondsHand = document.querySelector(".hand-seconds");

const setTime = () => {
  const currentTime = new Date();
  const secondsRatio = currentTime.getSeconds() / 60;
  const minutesRatio = (secondsRatio + currentTime.getMinutes()) / 60;
  const hoursRatio = (minutesRatio + currentTime.getHours()) / 12;

  secondsHand.style.setProperty("--rotation", secondsRatio * 360);
  minutesHand.style.setProperty("--rotation", minutesRatio * 360);
  hoursHand.style.setProperty("--rotation", hoursRatio * 360);
};

setInterval(setTime, 1000);

setTime();

Conclusion - Analog clock for improving your web development skills

Learning how to create an analog clock using HTML, CSS, and JavaScript is not only a great way to improve web development skills but it also gives you a beautiful tool that you can use on your website or simply share with others. Now it's time for you to experiment with the code - change the styling we created together and make an analog clock that you will be truly proud of!