HTML Clock — In Real Time

A somewhat interactive clock. And by that I mean animated HTML clock.

CSS — Visual Dictionary

Click here for the Amazon page and “Look Inside.

What is this? A CSS desk reference to remind you of many common CSS properties with the accompanying visual diagrams explaining how they work.

Interested? Grab your copy here.

— JavaScript Teacher
Follow me @js_tut on Twitter.

HTML Clock — In Real Time

Here is what I came up with. No images were used to create it!

HTML Clock with interactive JavaScript hands.

No images were used to create it. Still want proof? No problem. Here is the same clock with white background and border: 1px solid black:

The hands and notches are just HTML elements cleverly positioned and rotated using math. In particular the sin and cosine functions. See JavaScript code below to see how it was achieved.

Wait… are these round HTML elements? Precisely! They can be created by maxing out the border-radius property, by setting it to a high value like 1000px or at least the exact width or height of the initial element.

This clock demonstrates how together with CSS and JavaScript it’s possible to create slightly more interesting things… where HTML semantics are only about 33% of the source code. Large majority is spent in CSS and JavaScript calculations.

In this article I’ll provide the code I wrote to make this clock. It’s a pretty straightforward process.

HTML

The HTML is pretty straightforward. It’s just a few lines of code:

<div id = "clock-rim">
<div id = "clock-face">
<div id = "notch-container"></div>
<div id = "brand">HTML<br/>clock</div>
<div id = "hour"></div>
<div id = "minute"></div>
<div id = "second"></div>
<div id = "center"></div>
</div>
</div>

CSS

/* -- Border is required for #clock-face top-margin to work
in this case, I used a transparent border
because it doesn't really *need* to be visualized -- */
div { border: 1px solid transparent; }
/* -- The outside rim of the clock with gradient -- */
#clock-rim {
display: block;
position: relative;
width: 300px;
height: 300px;
background: linear-gradient(gray, black);
border-radius: 150px;
}
/* -- Clock's face -- */
#clock-face {
display: block;
position: relative;
width: 260px;
height: 260px;
margin: 19px auto;
border-radius: 150px;
background: white;
}
/* -- Second hand -- */
#second { position: absolute; top: 123px; left: 128px; width: 100px; height: 2px; border: 1px solid transparent; border-radius: 5px; transform: unset; background: green; transform-origin: 1px 1px; }
/* -- Minute hand -- */
#minute { position: absolute; top: 123px; left: 128px; width: 100px; height: 4px; border: 1px solid transparent; border-radius: 5px; transform: unset; background: red; transform-origin: 2px 2px; }
/* -- Hour hand -- */
#hour { position: absolute; top: 123px; left: 128px; width: 50px; height: 4px; border: 1px solid transparent; border-radius: 5px; transform: unset; background: blue; transform-origin: 2px 2px; }
/* -- Center of the clock -- */
#center { position: absolute; top: 118px; left: 120px; width: 16px; height: 16px; background: white; border: 1px solid gray; border-radius: 16px; }
/* -- "HTML clock"  in a box -- */
#brand { position: absolute; top: 110px; left: 165px; border: 1px solid gray; border-radius: 5px; width: 50px; height: 40px; font-family: Verdana; font-size: 11px; text-align: center; line-height: 20px; }
/* -- Notches container -- */
#notch-container { width: 260px; height: 260px }
/* -- Hourly notch (thicker, but sparse) -- */
.notch { position: absolute; width: 10px; height: 2px; background: black; border-radius: 5px 5px 5px 5px; }
/* -- Minute notch (thin) -- */
.thin { position: absolute; width: 10px; height: 1px; border-top: 1px solid gray; }

JavaScript

Finally, the JavaScript for this HTML clock will take care of drawing the notches by adjusting their position across the clock’s face. Note a little conversion from degrees to radians is required for this step.

/* -- Convert degrees to radians (actually unused here :-) -- */
function deg2rad(d) { return (2 * d / 360) * Math.PI; }
/* -- Progress the clock's hands every once in a while -- */
setInterval(() => {
let minute = document.getElementById("minute");
let hour = document.getElementById("hour");
let second = document.getElementById("second");
  /* -- note retracing by 90 degrees, this is just the way I calculated the hands, the "0" angle is at 3PM, not 12PM, -- */
let S = new Date().getSeconds() * 6 - 90;
let M = new Date().getMinutes() * 6 - 90;
let H = new Date().getHours() * 30 - 90;

second.style.transform = 'rotate(' + S + 'deg)';
minute.style.transform = 'rotate(' + M + 'deg)';
hour.style.transform = 'rotate(' + H + 'deg)';

}, 10); /* -- update the clock fast enough -- */
/* -- Helps calculate the angle of each hand on the clock -- */
function vec2ang(x, y) {
angleInRadians = Math.atan2(y, x);
angleInDegrees = (angleInRadians / Math.PI) * 180.0;
return angleInDegrees;
}
/* -- Let's calculate position and angle of clock's notches-- */
let nc = document.getElementById("notch-container");
let angle = 0;
let rotate_x = 120;
let rotate_y = 0;
/* -- Calculate the 60 notches for seconds and minutes -- */
for (let i = 0; i < 60; i++) {
  let thin = document.createElement("div");
let x = rotate_x * Math.cos(angle) - rotate_y * Math.cos(angle);
let y = rotate_y * Math.cos(angle) + rotate_x * Math.sin(angle);
let r = vec2ang(x, y);
thin.className = "thin";
thin.style.left = 122 + x + "px";
thin.style.top = 127 + y + "px";
thin.style.transform = "rotate(" + r + "deg)";
nc.appendChild(thin);
angle += (Math.PI / 300) * 10;
}
// reset angle parameters
angle = 0; rotate_x = 120; rotate_y = 0;
/* -- Calculate the thicker notches for hour hand -- */
for (let i = 0; i < 12; i++) {
  let notch = document.createElement("div");
let x = rotate_x * Math.cos(angle) - rotate_y * Math.cos(angle);
let y = rotate_y * Math.cos(angle) + rotate_x * Math.sin(angle);
let r = vec2ang(x, y);
notch.className = "notch";
notch.style.left = 122 + x + "px";
notch.style.top = 127 + y + "px";
notch.style.transform = "rotate(" + r + "deg)";
nc.appendChild(notch);
angle += (Math.PI / 60) * 10;
}

The JavaScript code will also progress the second, minute and hourly hands with setInterval. In JavaScript you can use getSeconds, getMinutes and getHours methods of the object returned from new Date to get your local system clock values from the Operating System.

You can check out the result at this fiddle I created: https://jsfiddle.net/7ngueqh8/128/