Looking to build a stylish dual clock UI using HTML, CSS, and JavaScript? In this tutorial, you’ll learn how to create a modern analog and digital clock with functional time and date display, complete with animated clock hands and a digital screen that updates every second.
This project is ideal for beginners exploring time-based UI projects, or developers wanting to showcase functional UI components using pure front-end technologies. Let’s build a responsive dual clock UI that combines both analog elegance and digital clarity.
What is a Dual Clock UI?
A dual clock UI is a user interface that combines both an analog clock (with hour, minute, and second hands) and a digital clock (with numeric time display). It provides users with a visually appealing and accurate way to keep track of the current time and date, all in one component.
This type of dual clock UI is commonly used in smartwatches, dashboard widgets, embedded IoT systems, and modern web dashboards where time tracking is critical.
HTML Structure for the Dual Clock
We begin by setting up the base structure using HTML. It includes elements for the analog clock hands, hour and minute markers, a digital time area, date container, and an AM/PM indicator.
This section is lightweight but well-structured to make space for both analog and digital clock elements. All clock hands, markers, and the digital panel are placed inside a clock-container
.
<div class="main-container centered-flex">
<div class="outer centered-flex">
<div class="inner">
<div class="clock-container">
<ul class="h-marking centered-flex">
<li style="--i:0"></li>
<li style="--i:1"></li>
<li style="--i:2"></li>
<li style="--i:3"></li>
<li style="--i:4"></li>
<li style="--i:5"></li>
</ul>
<ul class="m-marking centered-flex">
<li style="--i:1"></li>
<li style="--i:2"></li>
<li style="--i:3"></li>
<li style="--i:4"></li>
<li style="--i:6"></li>
<li style="--i:7"></li>
<li style="--i:8"></li>
<li style="--i:9"></li>
<li style="--i:11"></li>
<li style="--i:12"></li>
<li style="--i:13"></li>
<li style="--i:14"></li>
<li style="--i:16"></li>
<li style="--i:17"></li>
<li style="--i:18"></li>
<li style="--i:19"></li>
<li style="--i:21"></li>
<li style="--i:22"></li>
<li style="--i:23"></li>
<li style="--i:24"></li>
<li style="--i:26"></li>
<li style="--i:27"></li>
<li style="--i:28"></li>
<li style="--i:29"></li>
</ul>
<div class="hands centered-flex">
<div class="hour-hand"></div>
<div class="minute-hand"></div>
<div class="second-hand"></div>
<div class="dot"></div>
</div>
<div class="date centered-flex"><span></span></div>
<div class="indicator centered-flex"></div>
<div class="digital-clk centered-flex">
<div class="time centered-flex">
<span class="value"></span>
<span class="colon">:</span>
<span class="value"></span>
<span class="colon">:</span>
<span class="value"></span>
</div>
</div>
</div>
<div class="top-text">DUAL TIME</div>
<div class="func-text">
<span>LIGHT</span>
<span>ST/SP</span>
<span>RESET</span>
<span>MODE</span>
</div>
<span class="center-text">SPORTS</span>
</div>
<div class="buttons">
<span></span><span></span><span></span><span></span><span></span>
</div>
</div>
</div>
This layout mimics a sports watch UI with surrounding buttons and textual indicators. The use of flexbox ensures responsive alignment for different devices.
Styling the Dual Clock Using CSS
The design takes inspiration from digital sport watches, using gradients, inner shadows, clip paths, and rounded shapes to create a realistic clock feel. All hour and minute markings are created using transform: rotate(...)
, and placed with ul
lists and custom CSS variables. The clip-path
property adds polish to the digital sections and AM/PM indicator.
@font-face {
font-family: 'CustomFont';
src: url("https://db.onlinewebfonts.com/t/61b4eaee5625d47bb7215f205e44f580.ttf")format("truetype");
}
.main-container {
min-width: 300px;
min-height: 100vh;
}
.outer {
width: 12rem;
height: 12rem;
border-radius: 50%;
position: relative;
background: radial-gradient(#9b9b9b 50%, black);
}
.inner {
width: 10rem;
height: 10rem;
position: relative;
border-radius: 50%;
background: #2d2d2d;
}
.clock-container,
.clock-container ul {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.h-marking:after {
content: '';
z-index: 1;
width: 80%;
height: 80%;
border-radius: 50%;
position: absolute;
background-color: #2d2d2d;
}
.h-marking li {
width: .4rem;
height: 10rem;
z-index: 1;
list-style: none;
position: absolute;
background: linear-gradient(to right, white, #555555, white);
clip-path: polygon(0% 0%, 100% 0%, 0% 50%, 100% 100%, 0% 100%, 100% 50%);
}
.h-marking li {
transform: rotate(calc(var(--i) * 30deg));
}
.m-marking li {
width: .01rem;
height: 100%;
list-style: none;
background: white;
}
.m-marking li {
transform: rotate(calc(var(--i) * 6deg));
}
ul.m-marking:after {
content: '';
width: 94%;
height: 94%;
border-radius: 50%;
position: absolute;
background: #2d2d2d;
}
.hands {
width: 100%;
height: 100%;
}
.hour-hand,
.minute-hand,
.second-hand {
top: 50%;
z-index: 2;
position: absolute;
transform-origin: center 95%;
transform: translateY(-95%) rotate(0deg);
background: linear-gradient(to right, white, #8e8888, white);
}
.hour-hand {
width: 5%;
height: 25%;
clip-path: polygon(50% 0, 80% 8%, 100% 95%, 50% 100%, 0% 95%, 20% 8%);
}
.minute-hand {
width: 4%;
height: 40%;
clip-path: polygon(50% 0, 80% 8%, 100% 95%, 50% 100%, 0% 95%, 20% 8%);
}
.second-hand {
width: 1%;
height: 45%;
z-index: 3;
border-radius: 1rem;
transform-origin: center 85%;
transform: translateY(-85%) rotate(0deg);
}
.dot {
width: 0.2rem;
height: 0.2rem;
z-index: 3;
border-radius: 50%;
position: absolute;
background: #000000;
}
.digital-clk {
bottom: 16%;
clip-path: polygon(0% 20%, 15% 20%, 30% 0%, 70% 0%, 85% 20%, 100% 20%, 100% 55%, 85% 100%, 15% 100%, 0% 55%);
}
.date,
.digital-clk {
width: 68%;
height: 22%;
left: 50%;
z-index: 1;
position: absolute;
background: #030303;
transform: translateX(-50%);
box-shadow: inset 0px 0px 2px 2px #4f4f4feb;
}
.time {
color: white;
font-family: 'CustomFont';
width: 100%;
font-size: 1.4rem;
}
.value {
width: 22%;
text-align: center;
font-weight: bold;
letter-spacing: .05rem;
}
.colon {
font-size: 1.4rem;
width: 5%;
text-align: center;
margin-bottom: .4rem;
}
.time span:nth-child(4) {
left: 58%;
}
.top-text {
position: absolute;
color: white;
z-index: 1;
top: 13%;
font-weight: bold;
font-size: .4rem;
left: 50%;
transform: translate(-50%);
}
.date {
top: 19%;
clip-path: polygon(20% 0%, 80% 0%, 100% 60%, 100% 100%, 0 100%, 0% 60%);
}
.date span {
color: white;
font-size: 0.9rem;
word-spacing: .3rem;
font-family: 'CustomFont';
font-weight: bold;
}
.buttons span {
width: .4rem;
height: 1rem;
background: linear-gradient(to bottom, #a5a5a5, black 50%, #acacac);
position: absolute;
list-style: none;
border-radius: 50% 0 0 50%;
z-index: -1;
}
.buttons span:nth-child(1) {
left: 12%;
top: 10%;
transform: rotate(43deg);
}
.buttons span:nth-child(2) {
right: 12%;
top: 10%;
transform: rotate(135deg);
}
.buttons span:nth-child(3) {
right: 12%;
bottom: 10%;
transform: rotate(225deg);
}
.buttons span:nth-child(4) {
left: 12%;
bottom: 10%;
transform: rotate(315deg);
}
.buttons span:nth-child(5) {
right: -3.5%;
top: 43%;
border: 5px double #6c6c6c40;
width: .8rem;
height: 1.6rem;
transform: rotate(180deg);
}
.func-text span {
font-size: .4rem;
color: #bbbbbb;
position: absolute;
}
.func-text span:nth-child(1) {
left: 13%;
top: 17%;
transform: rotate(315deg);
}
.func-text span:nth-child(2) {
right: 13%;
top: 17%;
transform: rotate(45deg);
}
.func-text span:nth-child(3) {
right: 13%;
bottom: 17%;
transform: rotate(315deg);
}
.func-text span:nth-child(4) {
left: 13%;
bottom: 17%;
transform: rotate(45deg);
}
.center-text {
color: #c5c5c5;
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 1;
font-size: .5rem;
right: 20%;
text-shadow: 0px 1px 1px black;
}
.indicator {
font-size: .6rem;
width: 17%;
height: 17%;
font-weight: bold;
color: white;
font-family: 'CUSTOMFONT';
background: black;
position: absolute;
left: 16%;
top: 45%;
box-shadow: inset 0px 0px 2px 2px #4f4f4feb;
z-index: 1;
border-radius: 50%;
}
.centered-flex {
display: flex;
justify-content: center;
align-items: center;
}
This project doesn’t rely on any external UI library. Instead, it uses pure CSS for styling, which helps keep the component lightweight. Want to create more time-based UIs? This analog + digital clock UI project is a perfect starting point to explore creative time displays using HTML and CSS.
Making the Clock Functional with JavaScript
Now comes the real-time logic. JavaScript updates the rotation of each clock hand (hour, minute, second) based on the current time. It also updates the digital numbers and current date every second. Using setInterval()
, the UI dynamically refreshes:
const hr_hand = document.querySelector(".hour-hand");
const min_hand = document.querySelector(".minute-hand");
const sec_hand = document.querySelector(".second-hand");
const val = document.querySelectorAll(".time .value");
const dt = document.querySelector('.date');
const options = { weekday: 'short', month: 'short', day: 'numeric' };
const indicator = document.querySelector('.indicator');
setInterval(() => {
let date = new Date();
dt.firstElementChild.innerText = date.toLocaleDateString('en-US', options);
let h = date.getHours();
let m = date.getMinutes();
let s = date.getSeconds();
indicator.innerText = h >= 12 ? 'PM' : 'AM'
h = h > 12 ? h - 12 : h
let ah = 30 * h + m / 2 + s / 120;
let am = 6 * m + s / 10;
let as = 6 * s;
hr_hand.style.transform = `translateY(-95%) rotate(${ah}deg)`;
min_hand.style.transform = `translateY(-95%) rotate(${am}deg)`;
sec_hand.style.transform = `translateY(-85%) rotate(${as}deg)`;
val[0].innerText = h > 9 ? h : '0' + h;
val[1].innerText = m > 9 ? m : '0' + m;
val[2].innerText = s > 9 ? s : '0' + s;
}, 1000)
This method keeps both analog and digital sections of the dual time clock UI in sync. The JavaScript logic ensures accuracy while maintaining fluid animation.
Use Cases for This Analog + Digital Dual Clock UI
This stylish dual clock component can be used in several real-world projects:
- Smartwatch UI Mockups – Represent real-time watch interfaces with date and digital panel
- Web Dashboards – Display time-sensitive data clearly using analog + digital clocks
- Mobile Apps – Integrate compact clock widgets with both styles for better UX
- UI/UX Portfolios – Showcase your mastery in creating responsive, animated clock UIs
- Productivity Tools – Embed as a real-time component in task managers or alarm apps
Why Build an Analog and Digital Clock in JavaScript?
Creating a clock using HTML, CSS, and JavaScript is one of the best ways to practice DOM manipulation, CSS transforms, date/time handling, and dynamic updates.
It’s also a fun challenge that results in a visually engaging and functional UI. You’ll not only learn how to rotate clock hands using angles but also how to build responsive layouts using pure HTML and CSS.
Final Thoughts
This dual clock UI combines the best of both worlds—an animated analog clock with detailed hands and a digital time section that clearly displays the current time and date.
Whether you’re building a JavaScript time widget, a smartwatch simulation, or just exploring creative CSS layouts, this analog + digital clock UI is a valuable project to add to your portfolio.
Give it your own twist—customize the theme, adjust the layout, or expand it with time zone support.