Creative Visual Effects

Analog Clock

A delicate mechanical watch face that turns in real time according to local time.

HTMLCSSJavaScriptClock
With JavaScript enabled, you can edit, run, and save this example. The fixed source is as follows:
<!doctype html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Analog Clock</title>
  <style>
    * { box-sizing: border-box; }
    body { min-height: 100vh; margin: 0; display: grid; place-items: center; padding: 24px; color: #2b2923; font-family: "Baskerville", "STSong", serif; background: #c9bda4; background-image: radial-gradient(circle at 20% 20%, rgba(255,255,255,.35), transparent 30%), repeating-linear-gradient(90deg, rgba(82,61,40,.025) 0 1px, transparent 1px 5px); }
    main { width: min(620px, 100%); text-align: center; }
    .eyebrow { color: #775f42; font: 800 10px/1 "Courier New", monospace; letter-spacing: .3em; }
    h1 { margin: 10px 0 30px; font-size: clamp(33px, 7vw, 54px); font-weight: 500; }
    .clock-case { position: relative; width: min(390px, 80vw); aspect-ratio: 1; margin: auto; padding: 20px; border-radius: 50%; background: linear-gradient(145deg, #6d4c2f, #bd9365 45%, #51371f); box-shadow: 0 30px 60px rgba(51,37,24,.32), inset 0 0 0 3px rgba(255,255,255,.26), inset 0 0 0 9px rgba(40,25,14,.25); }
    .face { position: relative; width: 100%; height: 100%; border: 1px solid #b8a888; border-radius: 50%; background: radial-gradient(circle, #faf5e8 0 58%, #eee4cf 80%, #c8b58f); box-shadow: inset 0 0 24px rgba(65,48,29,.2); }
    .tick { position: absolute; inset: 9px 50% 50%; width: 1px; transform-origin: 50% 100%; }
    .tick::before { content: ""; display: block; width: 1px; height: 8px; background: #6e6759; }
    .tick.major::before { width: 3px; height: 14px; margin-left: -1px; background: #282722; }
    .number { position: absolute; color: #2b2923; font-size: clamp(20px, 5vw, 29px); font-weight: 700; transform: translate(-50%, -50%); }
    .n12 { left: 50%; top: 15%; } .n3 { left: 85%; top: 50%; } .n6 { left: 50%; top: 85%; } .n9 { left: 15%; top: 50%; }
    .maker { position: absolute; top: 30%; left: 50%; transform: translateX(-50%); color: #8c7d63; font: 800 9px/1 "Courier New", monospace; letter-spacing: .15em; }
    .hand { position: absolute; left: 50%; bottom: 50%; border-radius: 999px; transform-origin: 50% 100%; }
    .hour { width: 7px; height: 24%; margin-left: -3.5px; background: #272722; }
    .minute { width: 4px; height: 33%; margin-left: -2px; background: #3a3932; }
    .second { width: 2px; height: 38%; margin-left: -1px; background: #a74336; }
    .pin { position: absolute; left: 50%; top: 50%; width: 18px; height: 18px; border: 4px solid #eee4cf; border-radius: 50%; background: #a74336; box-shadow: 0 1px 4px rgba(0,0,0,.3); transform: translate(-50%, -50%); }
    .digital { display: inline-flex; gap: 12px; align-items: center; margin-top: 25px; padding: 10px 16px; border: 1px solid rgba(72,56,37,.24); border-radius: 999px; color: #594d3d; font: 700 12px/1 "Courier New", monospace; background: rgba(250,245,232,.42); }
    .digital time { color: #9c4337; font-size: 14px; }
  </style>
</head>
<body>
  <main><span class="eyebrow">LOCAL TIMEPIECE · NO. 12</span><h1>Let time be seen</h1>
    <div class="clock-case"><div id="face" class="face" aria-label="Analog Clock"><span class="number n12">12</span><span class="number n3">3</span><span class="number n6">6</span><span class="number n9">9</span><span class="maker">CHRONOS</span><i id="hour" class="hand hour"></i><i id="minute" class="hand minute"></i><i id="second" class="hand second"></i><i class="pin"></i></div></div>
    <div class="digital"><span id="date"></span><time id="digitalTime"></time></div>
  </main>
  <script>
    const face = document.querySelector('#face');
    for (let index = 0; index < 60; index += 1) {
      const tick = document.createElement('i'); tick.className = `tick${index % 5 === 0 ? ' major' : ''}`; tick.style.transform = `rotate(${index * 6}deg)`; face.prepend(tick);
    }
    function updateClock() {
      const now = new Date();
      const seconds = now.getSeconds();
      const minutes = now.getMinutes() + seconds / 60;
      const hours = now.getHours() % 12 + minutes / 60;
      document.querySelector('#second').style.transform = `rotate(${seconds * 6}deg)`;
      document.querySelector('#minute').style.transform = `rotate(${minutes * 6}deg)`;
      document.querySelector('#hour').style.transform = `rotate(${hours * 30}deg)`;
      document.querySelector('#digitalTime').textContent = now.toLocaleTimeString('zh-CN', { hour12: false });
      document.querySelector('#date').textContent = now.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric', weekday: 'short' });
    }
    updateClock();
    window.setInterval(updateClock, 1000);
  </script>
</body>
</html>
Page feedbackFound an issue or have suggestions for improvement?
Feedback features need to be used in the online version

Please enable JavaScript in the online version before submitting; local features of the current tool or example are not affected.

Go to the online version for feedback