In this video, we create a Minimal Dot Clock with 24-hour format using pure HTML, CSS, and JavaScript.
This modern digital clock UI uses animated dots to represent hours, minutes, and seconds, making it perfect for dashboard designs, portfolios, and creative web projects.
✨ What you’ll learn:
- Build a 24-hour digital clock in JavaScript
- Create a minimal dot-based UI with CSS
- Real-time clock updates without libraries
- Clean and modern frontend design
📌 Best for: Beginners & frontend developers
📌 No frameworks | No libraries | Pure JavaScript
👉 Don’t forget to Like 👍, Share 📤, and Subscribe 🔔 for more frontend UI tutorials!
HTML:
Create a HTML file and add the following code:
<div id="clock" class="clock">
<div class="ring hours"></div>
<div class="ring minutes"></div>
<div class="ring seconds"></div>
<div id="time" class="time"></div>
</div>
CSS:
Create a CSS file and add the following code:
@import url(https://fonts.bunny.net/css?family=roboto-mono:100,700);
@layer base, demo;
@layer demo {
:root{
--time-display: none;
--time-display: block;
}
.clock {
--clock-radius: clamp(120px, 15vw, 340px);
--time-clr: light-dark(rgba(0 0 0 / .5),rgba(255 255 255 / .35));
--dot-radius: 10px;
--dot-bg: light-dark(rgba(0 0 0 / .5),rgba(255 255 255 / .6));
--dot-opacity: .2;
--dot-hours-clr: rgb(0, 105, 168);
--dot-mins-clr: rgb(0, 188, 255);
--dot-secs-clr: rgb(251, 44, 54);
--dot-hours-w: clamp(7px, 1vw,16px);
--dot-mins-w: clamp(5px, .75vw,12px);
--dot-secs-w: clamp(5px, .75vw,12px);
--dot-hours-h: clamp(20px, 5vw,60px);
--dot-mins-h: clamp(10px, 2vw,25px);
--dot-secs-h: var(--dot-secs-w);
--dot-hours-ratio: 1/4;
--dot-mins-ratio: 1/3;
--dot-secs-ratio: 1/1;
width: calc(var(--clock-radius) * 2);
height: calc(var(--clock-radius) * 2);
border-radius:50%;
position: relative;
display: grid;
place-items: center;
& > *{
grid-area: 1/1;
}
}
.time{
display: var(--time-display);
color: var(--time-clr);
font-size: clamp(2rem, 3.5vw + .45rem, 4rem);
font-family: 'Roboto Mono', monospace;
}
.dot {
position: absolute;
inset:0;
margin: auto;
width: var(--dot-w,16px);
height: var(--dot-h,16px);
border-radius: var(--dot-radius);
background-color: var(--dot-bg);
opacity: var(--dot-opacity);
}
.seconds{
--dot-opacity: 0;
--dot-w: var(--dot-secs-w);
--dot-h: var(--dot-secs-h);
& > .dot{
--dot-bg: var(--dot-secs-clr);
}
& > .dot.active{
--dot-opacity: 1;
}
}
.minutes{
--dot-w: var(--dot-mins-w);
--dot-h: var(--dot-mins-h);
& > .dot:nth-child(5n + 1) {
--dot-opacity: 0;
}
& > .dot.active{
--dot-bg: var(--dot-mins-clr);
--dot-opacity: 1;
}
}
.hours{
--dot-w: var(--dot-hours-w);
--dot-h: var(--dot-hours-h);
& > .dot.active{
--dot-bg: var(--dot-hours-clr);
--dot-opacity: 1;
}
}
}
@layer base {
* {
box-sizing: border-box;
}
:root {
color-scheme: light dark;
--bg-dark: rgb(10, 10, 10);
--bg-light: rgb(248, 244, 238);
--txt-light: rgb(10, 10, 10);
--txt-dark: rgb(245, 245, 245);
--line-light: rgba(0 0 0 / .25);
--line-dark: rgba(255 255 255 / .25);
--clr-bg: light-dark(var(--bg-light), var(--bg-dark));
--clr-txt: light-dark(var(--txt-light), var(--txt-dark));
--clr-lines: light-dark(var(--line-light), var(--line-dark));
}
body {
background-color: var(--clr-bg);
color: var(--clr-txt);
min-height: 100svh;
margin: 0;
padding: 2rem;
font-family: "Jura", sans-serif;
font-size: 1rem;
line-height: 1.5;
display: grid;
place-items: center;
gap: 2rem;
}
h1 {
margin: 0;
font-size: 1.2rem;
}
.msg-supports {
font-size: 0.8rem;
}
}
JavaScript:
Create a JS file and add the following code:
console.clear();
const clock = document.getElementById('clock');
const rings = {
hours: { el: clock.querySelector('.hours'), numbers: 12 },
minutes: { el: clock.querySelector('.minutes'), numbers: 60 },
seconds: { el: clock.querySelector('.seconds'), numbers: 60 },
};
Object.entries(rings).forEach(([key, item]) => {
item.el.innerHTML = '';
for (let i = 0; i < item.numbers; i++) {
const dot = document.createElement('div');
dot.className = 'dot';
const angle = (360 / item.numbers) * i;
dot.style.transform = `rotate(${angle}deg) translateY(calc((var(--clock-radius) + var(--dot-h) * .5) * -1))`;
item.el.appendChild(dot);
}
});
const prevActive = {
hours: null,
minutes: null,
seconds: null
};
function updateClock() {
const now = new Date();
const current = {
hours: now.getHours() % 12,
minutes: now.getMinutes(),
seconds: now.getSeconds()
};
for (const unit in current) {
const value = current[unit];
const ring = rings[unit].el;
if (prevActive[unit] !== value) {
if (prevActive[unit] !== null) {
ring.children[prevActive[unit]].classList.remove('active');
}
ring.children[value].classList.add('active');
prevActive[unit] = value;
}
}
const timeDiv = document.getElementById('time');
const displayHours = now.getHours().toString().padStart(2, '0');
const displayMinutes = current.minutes.toString().padStart(2, '0');
const displaySeconds = current.seconds.toString().padStart(2, '0');
timeDiv.textContent = `${displayHours}:${displayMinutes}:${displaySeconds}`;
requestAnimationFrame(updateClock);
}
updateClock();
html #css #javascript #digitalclock #24hourclock #dotclock #frontend #webdevelopment #uidesign #javascriptprojects
Happy coding!
