Beautiful SVG Clock with CSS animation and minimal JavaScript

Roman Balitsky
JavaScript developer
Tue Aug 16 2022
Here I am sharing the source code with some explanation of this beautiful SVG Clock, made relying mostly on CSS animation for smoothness and with minimal JavaScript.
JavaScript is used to initialise the animation offset for the time arcs, and the rest of the arc animation is done by CSS animation, allowing it to run very smooth.
More JavaScript code is used to make the numeric time representation tic. That is just an interval function called every second to update the values and restart the fade-away animation on the numbers.
The time arcs are drawn using SVG path arc. The drawing path template for them is:
M ${x+r+0.01} ${y} A ${r} ${r} 0 1 1 ${x+r-0.01} ${y}
  • M ${x+r+0.01} ${y} — command to set the starting point for drawing a path (in our case start of the arc). It sets it at the designated x and y offset positions, plus r (known for us later as radius), plus 0.01 pixel on x axis. Practically this point will be the noon time on the arc.
  • A ${r} ${r} — command to start drawing an arc with horizontal and vertical radius r.
  • 0 1 1 - arc drawing flags; the very first parameter is  set to 0 and isn't of any interest here, as it is used to rotate ovals; then the the first 1 makes the arc to draw a large circle just outside the start and end points; and the last 1 sets the direction clockwise, as drawing a clock is literally what this arc is used here for.
  • ${x+r-0.01} ${y} — the finish point of the arc. Again noon time but -0.01 pixel on x axis: almost where the starting point is, just slightly left of it.
Here is an illustration of how everything described above forms the arc:
Animation of the arc being slowly drawn requires a trick. Practically the arc is always drawn, just the "incomplete" part of it is made transparent and invisible. In order to achieve that, the stroke style is made dashed via the stroke-dasharray property, while the length of one sole dash (and therefore one sole gap between dashes) is set equal the entire circumference of the arc. Then, using the stroke-dashoffset property, we can control how much of the dash vs gap is present on the stroke. Zero offset means the dash is taking all over the the arc making it all visible. Contrary to setting stroke-dashoffset to the value of circumference of the arc and making it invisible, since the gap then takes the entire arc.