25 CSS Spinners 13 / 25

Clock Tick Sweep Spinner

A precise gold second-hand sweeps in discrete tick steps around a minimal dark clock face with 12 hour markers, using CSS steps() timing to simulate mechanical tick motion.

Pure CSS MIT licensed
Live Demo Open in tab

This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.

Open in playground

The code

<div class="sp-13">
  <div class="sp-13__clock">
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__tick"></div>
    <div class="sp-13__hand"></div>
    <div class="sp-13__center"></div>
  </div>
</div>
.sp-13,.sp-13 *,.sp-13 *::before,.sp-13 *::after{box-sizing:border-box;margin:0;padding:0}
.sp-13{
  --bg:#0d0d0d;
  --face:#111;
  --ring:#e8e0d0;
  --hand:#f5c518;
  --tick:rgba(232,224,208,0.4);
  display:flex;
  align-items:center;
  justify-content:center;
  min-height:100vh;
  background:var(--bg);
}
.sp-13__clock{
  position:relative;
  width:80px;
  height:80px;
  background:var(--face);
  border-radius:50%;
  border:2px solid var(--ring);
  box-shadow:0 0 0 1px rgba(232,224,208,0.1),inset 0 0 16px rgba(0,0,0,0.5);
}
.sp-13__tick{
  position:absolute;
  top:50%;
  left:50%;
  width:2px;
  height:6px;
  margin-left:-1px;
  background:var(--tick);
  transform-origin:bottom center;
  border-radius:1px;
}
.sp-13__tick:nth-child(1){transform:translateY(-100%) translateY(-27px) rotate(0deg)}
.sp-13__tick:nth-child(2){transform:translateY(-100%) translateY(-27px) rotate(30deg)}
.sp-13__tick:nth-child(3){transform:translateY(-100%) translateY(-27px) rotate(60deg)}
.sp-13__tick:nth-child(4){transform:translateY(-100%) translateY(-27px) rotate(90deg)}
.sp-13__tick:nth-child(5){transform:translateY(-100%) translateY(-27px) rotate(120deg)}
.sp-13__tick:nth-child(6){transform:translateY(-100%) translateY(-27px) rotate(150deg)}
.sp-13__tick:nth-child(7){transform:translateY(-100%) translateY(-27px) rotate(180deg)}
.sp-13__tick:nth-child(8){transform:translateY(-100%) translateY(-27px) rotate(210deg)}
.sp-13__tick:nth-child(9){transform:translateY(-100%) translateY(-27px) rotate(240deg)}
.sp-13__tick:nth-child(10){transform:translateY(-100%) translateY(-27px) rotate(270deg)}
.sp-13__tick:nth-child(11){transform:translateY(-100%) translateY(-27px) rotate(300deg)}
.sp-13__tick:nth-child(12){transform:translateY(-100%) translateY(-27px) rotate(330deg)}
.sp-13__hand{
  position:absolute;
  bottom:50%;
  left:50%;
  width:2px;
  height:26px;
  margin-left:-1px;
  background:var(--hand);
  border-radius:2px 2px 0 0;
  transform-origin:bottom center;
  box-shadow:0 0 4px var(--hand);
  animation:sp-13-tick 1s steps(60,end) infinite;
}
.sp-13__center{
  position:absolute;
  top:50%;
  left:50%;
  width:6px;
  height:6px;
  border-radius:50%;
  background:var(--hand);
  transform:translate(-50%,-50%);
  box-shadow:0 0 4px var(--hand);
}
@keyframes sp-13-tick{
  to{transform:rotate(360deg)}
}
@media (prefers-reduced-motion: reduce){
  .sp-13__hand{animation:none}
}

How this works

The clock face is a circle styled with a dark background and a subtle inset shadow for depth, with 12 small tick marks positioned using the same radial offset technique as clock hands — each tick is a thin rectangle placed at top:50%;left:50%, rotated by N×30deg, then translated outward. The 12 individual nth-child rules pre-rotate each tick to its hour position.

The hand element uses bottom:50% (so it grows upward from the pivot) with transform-origin:bottom center. Its animation uses steps(60, end) timing — this makes the hand snap to each of 60 discrete positions per revolution rather than smoothly easing, exactly replicating the tick-tick motion of a mechanical clock second hand.

Customize

  • Change the hand colour via --hand — a red (#e53935) hand on a white face creates a classic kitchen-timer look.
  • Add a minute hand by duplicating the hand element with a longer duration (60s) and a different colour.
  • Replace steps(60,end) with linear for a smooth sweep hand (quartz vs mechanical analogy).
  • Increase tick mark height from 6px to 10px and add a larger square every 3rd tick using nth-child(3n) for a more detailed clock face.
  • Wrap in a larger outer bezel div with a metallic background:conic-gradient(...) for a watch-case appearance.

Watch out for

  • steps(60,end) produces 60 positions per full rotation — for a spinner rather than a clock, steps(8,end) or steps(12,end) gives a crisper mechanical feel without requiring a full second-hand metaphor.
  • The tick marks use a specific translate distance tuned to the 80px wrapper — resizing the clock requires recalculating the translateY(-27px) offset to keep ticks inside the ring.
  • Using bottom:50% instead of top:50% for the hand positioning means the pivot point is at the visual centre — changing to top:50% and adjusting height will invert the hand direction.

Browser support

ChromeSafariFirefoxEdge
60+ 12+ 60+ 60+

steps() timing function well-supported; no modern-only APIs needed.

Search CodeFronts

Loading…