JavaScript30 - Day 2 (JS & CSS Clock)

This is day 2 in my #javascript30 journey. This is the free course from Wes Bos that lets you brush up on your JavaScript skills via 30 projects.

Yesterday we built an electric drumkit. You can keep track of all the projects we're building here.

Today we're creating a Clock.


Day 2 - CSS + JS Clock

Today we're creating a digital version of an analog clock using only HTML, CSS & JavaScript. No frameworks, no plug ins, no nothing. Just basic browser tools. Let's get into it.

We're starting the file that Wes provided that includes all the styling and the HTML we need. We only need to implement the magic via scripts.

The starter file gives us this output to start:

Starting file

The aim of today is that we will apply a rotate onto each of the hands (second, minute, hour) based on the current time.

We will also need to put some logic in place so that the hands don't rotate on the middle axis of the component. This is what it would look like if the hands rotate on the default axis:

CSS rotate on the middle axis

Go home clock; you're drunk.

We can fix this by transforming the origin via the CSS transform-origin. A transform-origin: 100%; fixes this by pushing the transform axis 100% to the right of the div.

Implement the Default Clock Hand Rotation

We want the hands of the clock to face the '12' by default. To do this we will need to rotate them 90 degrees. This is done via CSS with transform: rotate(90deg) applied to the .hand selector. It is a simple solution:

Clock with hands defaulting to 12

Calculate the Current Time

JavaScript has some pretty nifty build in processes for calculating the current time. We need our time to be calculated every second so this works out like this:

function setDate() {  
  const now = new Date()
}
setInterval(setDate, 1000)  
Set Hands to Rotate with the Current Time

Now that we know how to rotate the hands & can find the current time it is a process of putting these all together.

To animate the 'Second Hand' we need to:

  • Find the current seconds time
  • Calculate how much we should rotate the hand (current seconds / 60 * 360).
  • Allow for the default rotation (+90 onto the degrees calculation).
  • Alter the style on the Second Hand to transform to the resulting number of degrees.

This plays out in the script like this:

function setDate() {  
  const now = new Date()  
  const seconds = now.getSeconds()
  const secondsDegrees = seconds / 60 * 360 + 90
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`
}
setInterval(setDate, 1000)  

and displays like this:
Clock with second hand animation

Then it is a matter of replicating these calculations for the Minute & Hour hands. Remember that the hour hand only needs to be divided by 12, not 60.

Remove Flicker when Passing 12

There is currently a flicker when any of the hands go past 12. This is because the transformation sets back to the beginning and this animation is shown:

Clock with flicker

Bad, bad, not good.

Wes inishes off the tutorial with a couple of ideas of how you could fix this but doesn't show you how to do it. I removed the flicker by creating a function that removes the transition animation style when the hand passes the 12 (when the degrees are set to 90):

//Fixes the flicker as the clock resets transformation location
function checkFlicker(ele, deg) {  
  if (deg === 90) {
    ele.style.transition = 'all 0.0s'
  }
}

function setDate() {  
  const now = new Date()
  ...
  checkFlicker(secondHand, secondsDegrees)
  checkFlicker(minuteHand, minutesDegrees)
  checkFlicker(hourHand, hoursDegrees)
}

Once this is in place we have a fully functional analog style clock:

Clock with full animation

Now that everything has been done I have pushed this project live to a Firebase project. You can view it live here.

You can keep track of all the projects in this JavaScript30 challenge here.