Building a Pure JavaScript and CSS Analog Clock with Animation‑Delay
This tutorial demonstrates how to create a functional analog clock using only HTML, CSS keyframe animations, and a small JavaScript snippet that sets negative animation‑delay values so the clock starts synchronized with the current time.
This article explains how to build a simple analog clock using only HTML, CSS, and a minimal amount of JavaScript, based on Wes Bos' JavaScript30 challenge.
The clock's HTML structure consists of a .clock container, a .clock-face element, and three hand elements: .hour-hand, .min-hand, and .second-hand.
<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>CSS styles create a circular clock, position the hands, and define a @keyframes circle animation that rotates the elements. The second hand uses steps(60, end) for discrete movement, while minute and hour hands use linear timing.
.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);
}
.clock-face:after {
width: 1em;
height: 1em;
left: 50%;
top: 50%;
position: absolute;
content: '';
background-color: #a8c5d1;
border-radius: 50%;
box-shadow: 0 0 0 2px rgba(0,0,0,0.1),
0 0 10px rgba(0,0,0,0.2);
transform: translate(-50%, -50%);
}
.hand {
width: 50%;
height: 6px;
background: black;
position: absolute;
top: 50%;
transform-origin: 100%;
transform: rotate(90deg);
box-shadow: 0 0 0 0.1px #fff,
0 0 0 1px rgb(0 0 0 / 10%),
0 0 8px rgb(0 0 0 / 50%);
}
.second-hand {
height: 3px;
background-color: #ff0e0e;
border-bottom-left-radius: 100%;
border-top-left-radius: 100%;
}
.min-hand {
background-color: white;
width: 45%;
left: 5%;
}
.hour-hand {
background-color: white;
border-radius: 5px;
width: 40%;
height: 12px;
left: 10%;
}
@keyframes circle {
to { transform: rotate(1.25turn); }
}
.second-hand { animation: circle 60s steps(60, end) infinite; }
.min-hand { animation: circle 3600s linear infinite; }
.hour-hand { animation: circle 43200s linear infinite; }JavaScript retrieves the current time and sets a negative animation-delay on each hand so the animation starts at the correct position, after which the CSS animation runs autonomously.
const secondHand = document.querySelector('.second-hand');
const minsHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');
function init() {
const now = new Date();
const seconds = now.getSeconds();
secondHand.style.animationDelay = `-${seconds}s`;
const mins = now.getMinutes() * 60 + seconds;
minsHand.style.animationDelay = `-${mins}s`;
const hours = now.getHours() * 3600 + mins;
hourHand.style.animationDelay = `-${hours}s`;
}
init();The result is a self‑running analog clock that displays the actual time on page load, illustrating key front‑end concepts such as HTML markup, CSS layout, keyframe animations, and minimal JavaScript control.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ByteFE
Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
