Minimalist Radial Dot Clock
See the Pen Minimalist Radial Dot Clock.
Tech & Dependencies
Features
- ✓ Radial Layout
- ✓ requestAnimationFrame
- ✓ CSS Light-Dark Mode
Browser Support
Core
This is a Minimalist Radial Dot Clock. It visualizes time through three concentric rings of geometric dots (hours, minutes, seconds) rather than traditional sweeping hands. Its function is to provide an ambient, modern alternative to standard analog or digital readouts, integrating seamlessly into high-end, futuristic interfaces.
Specs
- Weight: ~3 KB. Zero external dependencies.
- Performance: High. The script utilizes
requestAnimationFramefor a smooth tick, but intelligently caches previous values (prevActive) so it only touches the DOM when a unit of time actually changes. - Theming / Customization: Fully governed by CSS variables. Colors, dot dimensions, and opacities are defined at the
.clockroot. It utilizes the modern CSSlight-dark()function for native theme switching. - Responsiveness: Scales dynamically using a
clamp()formula applied to the--clock-radiusvariable. - Graceful Degradation: [!] If JavaScript fails, the clock remains an empty circular layout. It lacks
<time>semantics and screen-reader accessibility for the visual layout.
Anatomy
- HTML: A structural shell. A
#clockcontainer holds three.ringdivs for the time units and a.timediv for the digital readout. - CSS: The visual engine. It establishes the grid overlay to stack the rings (
grid-area: 1/1). It defines the varying widths and heights for the dots based on their role (e.g., long ticks for hours, small circles for seconds) and handles the:has()logic for the visibility toggle. - JS: The logic controller. It dynamically generates the DOM nodes for the dots, calculates their static radial coordinates via trigonometry, and loops the active
.activeclass assignment based on the current system time.
Logic
The architectural efficiency of this snippet lies in its initial trigonometric layout and subsequent minimal DOM manipulation.
// Calculate radial position once
const angle = (360 / item.numbers) * i;
dot.style.transform = `
rotate(${angle}deg)
translateY(calc((var(--clock-radius) + var(--dot-h) * .5) * -1))
`;
// Update loop logic
if (prevActive[unit] !== value) {
if (prevActive[unit] !== null) {
ring.children[prevActive[unit]].classList.remove('active');
}
ring.children[value].classList.add('active');
prevActive[unit] = value;
}
Instead of rotating large div containers acting as invisible hands every frame, the JavaScript generates every possible dot (12 hours, 60 minutes, 60 seconds) on load and pushes them out to the perimeter using rotate and translateY. During the updateClock loop, the script simply swaps a single .active class. The prevActive check ensures the browser isn’t needlessly recalculating styles on all 132 elements 60 times a second.
Feel
Precise, quiet, and mechanical. The lack of CSS transitions on the dots means the time snaps forward instantly, mirroring the crisp, binary logic of a digital system rather than the analog sweeping of physical gears. It feels like a high-grade piece of telemetry equipment.


