Neu Clock
A 200 px raised analog clock with a 180 px carved dial, 12 hour markers and three hands that follow the device's real time, recomputed every second in JavaScript. As many clocks per page as you like.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Glassmorphism has 47 effects, including 6 free. Explore the category →
3 usage examples



How it works
Two discs in the #e0e5ec tint. The .neu-clock case (200 px) rises from the surface through #b8bec7 12px 12px 24px and #fff -12px -12px 24px; the .neu-clock-inner dial (180 px) is carved into it by 4 px / 8 px inset shadows. Twelve .neu-clock-mark markers turn around the center thanks to transform-origin: center 82px (8 px from the edge + 82 px = the dial's center): eight small 2 × 12 px in #9ca3af, four large 3 × 16 px in #6b7280 at 12, 3, 6 and 9. The hands start from the center (bottom: 50%, transform-origin: center bottom): hours 4 × 50 px in #374151, minutes 3 × 65 px in #6b7280, seconds 1.5 × 72 px in violet #8b5cf6, under a 10 px violet hub.
The JavaScript reads new Date() once a second and computes three angles: seconds at 6° per second, minutes at 6° per minute plus 0.1° per second (the hand glides between minutes), hours at 30° per hour plus 0.5° per minute. No CSS transition: the second hand jumps one notch every second, like a quartz movement, and never swings backwards from 59 to 0. The time is the visitor's device time, in their time zone. On every tick, the script also writes the time into the clock's aria-label (toLocaleTimeString, hours and minutes); the clock carries role="img".
The dial carries its twelve markers in the HTML, and their margin-left centers them exactly (−1 px and −1.5 px). The script targets no id: it animates every .neu-clock on the page, so a second clock is not stuck at the position written in the HTML — measured, two clocks pasted side by side show the same angle to the second. And .neu-clock-scene carries its surface (#e0e5ec, padding: 40px, enough for the 12 + 24 px shadow), so the relief does not depend on your page background.
Accessibility
- Live text alternative: the clock is an image (
role="img") whose name follows the time, e.g. “07:52”; it is only updated in the attribute, with no announcement every second, which avoids flooding a screen reader. If the time is the page's main information, also show it as visible text. - Contrast: on the
#e0e5ecdial, the#374151hour hand measures 8.1:1, the#6b7280minute hand 3.8:1, the violet second hand 3.3:1 and the large markers 3.8:1 — above the 3:1 required for graphics. The small#9ca3afmarkers (2.0:1) fall below: switch them to#6b7280if the clock must be read from a distance. - Motion: only the second hand moves, one notch per second, with no CSS animation.
prefers-reduced-motionis not handled; for a calm screen, hide it:@media (prefers-reduced-motion: reduce) { .neu-clock-hand--second { display: none } }. The code does not stop when the tab is hidden: the browser throttles the timer itself, with no effect on the time shown on return. - Nothing to reach with the keyboard: the clock is not interactive and takes no focus.
Browser compatibility
CSS: drop and inset box-shadow, transform: rotate() with a pixel transform-origin, border-radius: 50%. JavaScript: setInterval, Date, toLocaleTimeString, querySelectorAll(...).forEach (NodeList.forEach: Chrome 51, Firefox 50, Safari 10). Measured in Chromium, Firefox and WebKit (Playwright): 12 markers at equal distance from the center, second hand stepping once per second, two clocks in sync, no console error.
Without JavaScript, the dial shows its markers and hands frozen at the position written in the HTML (about 3:02): remove those inline styles if a wrong time bothers you more than a clock without hands.
The code
HTML structure to paste into your page (the CSS + JS come with Premium):
<div class="neu-clock-scene">
<div class="neu-clock" role="img" aria-label="Horloge">
<div class="neu-clock-inner">
<span class="neu-clock-mark neu-clock-mark--major" style="transform: rotate(0deg);"></span>
<span class="neu-clock-mark" style="transform: rotate(30deg);"></span>
<!-- … 10 more markers, 60 to 330° -->
<div class="neu-clock-dot"></div>
<div class="neu-clock-hand neu-clock-hand--hour"></div>
<div class="neu-clock-hand neu-clock-hand--minute"></div>
<div class="neu-clock-hand neu-clock-hand--second"></div>
</div>
</div>
</div>
The full HTML + CSS + JS of Neu Clock, ready to paste — plus all 840 effects. Or $299 once, lifetime access.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Size (CSS — .neu-clock 200 px, .neu-clock-inner 180 px) |
200 px | For 300 px, multiply by 1.5: 270 px dial, hands 75 / 97 / 108 px, markers at top: 12px with transform-origin: center 123px (dial radius − top). Or keep the CSS and scale with transform: scale(.6) on .neu-clock. |
Second hand (CSS — .neu-clock-hand--second) |
1.5 × 72 px, violet #8b5cf6 | display: none for a calm clock (waiting room, bedroom). For a continuous sweep instead of jumps: transition: transform 1s linear — but the hand will then spin backwards from 354° to 0°. |
Markers (HTML — 12 .neu-clock-mark, --major at 0, 90, 180 and 270°) |
4 large, 8 small | Keep only the four large ones for a clean dial, or add the --major class to all twelve. The angles are in each marker's style attribute. |
Time zone (JS — new Date()) |
device local time | To show Tokyo: var now = new Date(new Date().toLocaleString('en-US', { timeZone: 'Asia/Tokyo' })) in place of the first line of tick. |
Hand colors (CSS — #374151, #6b7280, #8b5cf6) |
dark gray, gray, violet | Keep at least 3:1 on #e0e5ec: a red #dc2626 second hand measures 3.8:1. |
FAQ
.neu-clock present at load, with no id. A clock your code adds later is not picked up: run the script again, or call it after inserting the HTML.Date.now() and add it in tick.