Wonderful Analog Clock using HTML, CSS, And JavaScript

Welcome to Day 2 of the JavaScript30 challenge, and today we’re going to build a wonderful Analog Clock with just HTML, CSS, and JavaScript.

If you want to know more about JavaScript30, watch the video below and go here

Those of you who want to know how will our finished project look like, click here

Starter Files

Before moving forward, copy the initial HTML, and CSS files from the snippets below and set up your local environment to get started

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <title>JS + CSS Clock</title>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <div class="clock">
      <div class="clock-face">
        <div class="hand hour-hand"></div>
        <div class="hand min-hand"></div>
        <div class="hand second-hand"></div>
      </div>
    </div>
    <script src="script.js"></script>
  </body>

</html>
html {
    background: #018DED url(https://unsplash.it/1500/1000?image=881&blur=5);
    background-size: cover;
    font-family: 'helvetica neue';
    text-align: center;
    font-size: 10px;
}

body {
  margin: 0;
  font-size: 2rem;
  display: flex;
  flex: 1;
  min-height: 100vh;
  align-items: center;
}

.clock {
  width: 30rem;
  height: 30rem;
  border: 20px solid white;
  border-radius: 50%;
  margin: 50px auto;
  position: relative;
  padding: 2rem;
  box-shadow:
    0 0 0 4px rgba(0,0,0,0.1),
    inset 0 0 0 3px #EFEFEF,
    inset 0 0 10px black,
    0 0 10px rgba(0,0,0,0.2);
}

.clock-face {
  position: relative;
  width: 100%;
  height: 100%;
  transform: translateY(-3px); /* account for the height of the clock hands */
}

.hand {
  width: 50%;
  height: 6px;
  background: black;
  position: absolute;
  top: 50%;
  transform-origin: 100%;
  transform: rotate(90deg);
  transition: all 0.05s;
  transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}
.hour-hand{
  width: 35%;
  top: 49.1%;
  left: 16%;
  height: 10px;
}
.second-hand{
  height: 4px;  
}

Once you’ve downloaded and set up the code locally, your HTML file will look like this

HTML File Structure

HTML file structure in this project is very easy –

  • Individual clock-hands are wrapped inside their respective divs
  • These divs are then wrapped inside another div with a CSS class of ‘clock-face’ which is then wrapped inside a final parent div

JavaScript Logic

I was having difficulty understanding the logic which Wes has done in the tutorial, so I have used my own way to make the clock function.

It will require some mathematics to calculate the movement of the hands of the clock so pay close attention.

Seconds-Hand

Objective: To rotate the hand by x degrees every second so that it completes 360 degrees once 60 seconds are over

Solution: To calculate the ideal degree of rotation, we have to divide 360/60 which will result in 6 degrees per second. It means when the hand is rotated for 6 degrees each second, it’ll complete the 360 degrees in a minute

Minutes-Hand

Objective: To rotate the hand by x degrees every minute so that it completes 360 degrees once 60 minutes are over

Solution: Again we’ll get the same 6 degrees, we have to rotate the clock for 6 degrees every minute for it to complete 360 degrees after an hour

Hours-Hand

Objective: To rotate the hand by x degrees every hour so that it completes 360 degrees after 12 hours + we have to also show the rotation in the hour hand which is caused by the movement of the minute hand

Solution:

  • The hour hand will complete 360 degrees in 12 hours which means it will complete 30 degrees every hour
  • There are 60 minutes in an hour, completion of these 60 minutes will cause a 30 degrees rotation in the hour hand which means that for every 2 minutes there is a 1-degree rotation in the hour hand
  • It means that apart from rotating the hour clock for 30 degrees after 60 minutes, we’ll also have to rotate it for ‘m/2’ minutes every minute

JavaScript Code

It’s time for us to shift the raw mathematical data above into real JavaScript code.

Let’s start from storing the respected clock hand elements into variables

const secondHand = document.querySelector('.second-hand')
const minuteHand = document.querySelector('.min-hand')
const hourHand = document.querySelector('.hour-hand')

Our next step is to create 3 separate functions to set the rotation of second, minute, and hour hands

function setSeconds() {
    const now = new Date() // Date() is a inbuilt JavaScript object used to work with dates and time
    const seconds = now.getSeconds() //.getSeconds is a Date() method to get seconds
    const secondsDegrees = (6 * seconds)
    secondHand.style.transform = `rotate(${secondsDegrees}deg)`
}

function setMinutes() {
    const now = new Date()
    const minutes = now.getMinutes() //.getMinutes is a Date() method to get minutes
    const minutesDegrees = (6 * minutes)
    minuteHand.style.transform = `rotate(${minutesDegrees}deg)`
}

function setHours() {
    const now = new Date()
    const hours = now.getHours() //.getHours is a Date() method to get hours
    const minutes = now.getMinutes()
    const hoursDegrees = (30 * hours) + (minutes/2)
    hourHand.style.transform = `rotate(${hoursDegrees}deg)`
}

And finally we’ll write 3 setInterval() so that the functions above call themselves again and again after each second.

setInterval(setSeconds, 1000)
setInterval(setMinutes, 1000)
setInterval(setHours, 1000)

Now, if you’ve followed the tutorial upto this point, your project should work fine, right??

No. Because we’re still missing one important piece of code.

If your clock is in working condition, you’ll notice that that it’s hands are 90 degrees behind the actual time

Why is that happening? Remember at the beginning of the article I showed you an still image of the clock where all the hands were pointing towards 12’O Clock??

Well that happened because we inserted the below code explicitly on the ‘hour’ class of the CSS

transform: rotate(90deg);

This code rotated our clock hands to 90 degrees long before we started working on our JavaScript

And because we erased the default rotation of the hands and added new rotation dynamically, it happened on the default horizontal hands of the clock which are pointing towards 8.45 AM/PM, and this caused us a fall of 90 degrees.

To remove this bug, we have to add ’90’ to our rotation variables, replace the old rotation variables with new ones given below

const secondsDegrees = (6 * seconds) + 90
 const minutesDegrees = (6 * minutes) + 90
 const hoursDegrees = (30 * hours) + (minutes/2) + 90

Conclusion

Congratulations 🎉, you’ve made this far and your clock should be working fine now.

If not or you have any other question or confusions regarding this project, shoot a comment below.

I’ll see you in the next post, till then,

Happy Coding 🙂

38