What You'll Build
In this tutorial, you'll build a CSS neon digital clock entirely from scratch — no libraries, no canvas, just HTML, CSS, and vanilla JavaScript. The clock displays live hours, minutes, and seconds using a 7-segment display system styled with neon glow effects, sits in a 3D perspective scene, and includes a glowing floor reflection.
This project is a step up from beginner work — it's ideal if you want to practice requestAnimationFrame, CSS 3D transforms, data attribute selectors, and dynamic DOM generation in one visually impressive project.
Key Features of This Neon Clock
requestAnimationFrame for smooth
rendering.drop-shadow filters create realistic neon tube glow on each digit
segment.preserve-3d and CSS keyframes animate a slow orbit around the clock.
[data-digit] selectors to show the correct
segments.vmin units throughout so the clock scales cleanly on any screen
size.Full Source Code (Free)
The project uses three files: HTML for the minimal container structure, CSS for the 3D scene and neon glow styling, and JavaScript for the digit generation and real-time update logic. Use the tabs to switch between them.
index.html in
your browser. The clock starts displaying the current time immediately — no server required.
How It Works — Step by Step
Here's a breakdown of the eight core techniques behind this neon digital clock, from DOM generation to the 3D scene setup.
Minimal HTML Structure
The HTML contains only a <main> element. All clock
segments, digits, colons, and reflection elements are generated and injected
by JavaScript, keeping the markup completely clean and the rendering logic
centralized in the JS file.
JavaScript Digit Generator
An addDigits() function creates a set of seven <span>
elements — one per segment of a 7-segment display. Each digit container receives a
data-digit attribute that CSS uses to show or hide the correct segments
for numbers 0–9.
Real-Time Clock with requestAnimationFrame
A recursive requestAnimationFrame(update) loop runs on every frame.
Inside the loop, new Date() reads the current time. When the seconds
value changes, the function updates data-digit on the relevant elements,
which triggers CSS to redraw the correct segments instantly.
CSS Neon Glow via drop-shadow
Active segments receive filter: drop-shadow(0 0 Xpx var(--glow-color))
with multiple layered shadow values. Because drop-shadow follows the
actual shape — not a bounding box — the glow hugs each bar segment precisely,
creating a convincing neon tube appearance.
3D Perspective Scene
The clock container uses transform-style: preserve-3d and
perspective: Xpx to enable 3D rendering. A CSS
@keyframes animation continuously rotates the container
around the Y-axis, creating a slow camera orbit that shows the clock
from slightly different angles over time.
data-digit CSS Selectors
Each of the 7 spans inside a digit has a positional class (top, mid, bot,
top-left, etc.). CSS rules like
[data-digit="7"] .top, [data-digit="7"] .top-right, [data-digit="7"] .bot-right { opacity: 1; }
activate only the segments needed for that digit, while all others remain dim.
Floor Reflection
JavaScript clones each digit group and appends it below the clock with
transform: scaleY(-1). A gradient mask-image
fades the reflection from fully opaque at the top to transparent at the bottom,
simulating a glowing surface below the clock.
Cross-Browser Safari Fixes
navigator.userAgent detects Safari and applies
-webkit- prefixed properties where needed.
Safari has historically had inconsistent support for
preserve-3d in combination with certain CSS filters,
so targeted overrides ensure consistent rendering.
drop-shadow filters on many elements simultaneously can
be GPU-intensive on lower-end devices. If you notice frame drops on mobile, reduce the number of shadow layers
or lower the blur radius in the filter values.
JavaScript & CSS Concepts Used
This project covers these intermediate-to-advanced web development techniques:
- requestAnimationFrame — Building a performant real-time update loop that syncs with the display refresh rate.
- Dynamic DOM Generation — Creating and injecting all clock elements programmatically from JavaScript.
- CSS Data Attribute Selectors — Using
[data-digit="X"]to conditionally style elements based on their data values. - CSS 3D Transforms —
transform-style: preserve-3d,perspective, androtateY()for 3D scenes. - CSS drop-shadow Filter — Layered glow effects that follow element shapes precisely.
- CSS vmin Units — Responsive sizing that scales with the smaller viewport dimension for consistent layouts.
- CSS mask-image — Gradient masks to fade the reflection element from visible to transparent.
- Cross-Browser Detection — UA detection and conditional styles for Safari compatibility.
Frequently Asked Questions
How do I create a real-time digital clock with JavaScript?
requestAnimationFrame() in a recursive loop. On each frame, call
new Date() and extract getHours(), getMinutes(),
and getSeconds(). When the seconds value changes, update your DOM elements
with the new time values. Full source code is in the tabs above.
How does the neon glow effect work in CSS?
filter: drop-shadow() with multiple layered values at
different blur radii and opacities. Unlike box-shadow,
drop-shadow follows the actual painted shape of the element — so for
thin bar segments, the glow hugs each bar rather than a rectangular boundary.
What is a 7-segment display and how is it built with CSS?
<span> styled as a horizontal or vertical bar.
CSS attribute selectors like [data-digit="3"] .top { opacity: 1; }
activate the correct segments for each number 0–9 while all others stay dim.
Why use requestAnimationFrame instead of setInterval?
requestAnimationFrame syncs with the display's refresh rate (~60fps),
resulting in smoother CSS transitions and better battery efficiency than
setInterval. It also automatically pauses when the tab is inactive,
saving CPU resources.
How does the 3D camera animation work?
transform-style: preserve-3d and a
perspective value set on its parent. A CSS @keyframes
animation continuously rotates the wrapper from rotateY(0deg) to
rotateY(360deg) over a long duration, creating a slow, continuous orbit.
Is this project good for beginner developers?
requestAnimationFrame, CSS 3D transforms, data attribute selectors,
and dynamic DOM generation. It's an ideal third or fourth project for someone
who has completed the basics and wants to build something visually impressive.
Conclusion
This CSS neon digital clock demonstrates how far vanilla web technologies can go. By combining requestAnimationFrame for real-time updates, CSS data attribute selectors for the 7-segment display system, drop-shadow filters for the neon glow, and CSS 3D transforms for the perspective scene — you get a production-quality visual project with zero dependencies.
Whether you're building a portfolio piece, learning advanced JavaScript timing, or just want to master CSS 3D — this project covers the real-world techniques that matter. Copy the code, change the glow color, adjust the animation speed, and make it yours.
Found this useful? Explore more HTML CSS JavaScript projects in the sidebar.