Create a pure CSS clock with SVG.
Recently I decided to learn how to write SVG (Scalable Vector Graphics) by hand, as well as SVG animations. I have been using CSS for quite some time but I hadn’t used the steps
animation timing function before. It’s basically a function that transitions elements step by step, for the duration of the animation. Here is a pen I created that illustrates how the steps
function works.
In this tutorial, we shall create this pure CSS clock. This tutorial is divided into two sections:
- Section 1 — Creating a static clock.
- Section 2 — Making the clock work.
Prerequisites
- Basic SVG concepts like how to draw a line and a circle.
- CSS animations with keyframes.
- CSS transforms.
Section 1 — Creating a static clock.
First, Let’s create an outline of the shape of the clock. It’s a simple circle with a white fill and a black stroke.
HTML
The viewBox property of the SVG specifies the x, y, width and height properties respectfully. The radius of the circle is set to19
so that it can fit into the viewBox.
<svg viewBox="0 0 40 40">
<circle cx="20" cy="20" r="19" />
</svg>
CSS
Give the background a light gray color and style the SVG element.
html {
background: #dedede;
}svg {
width: 400px;
fill: white;
stroke: black;
stroke-width: 1;
stroke-linecap: round;
}
Add 12 marks to indicate the hours on a clock.
HTML
The <g>
tag groups the line
elements so that, later we can move them at once using CSS transforms. Note that the lines are 12 in total (one for each hour) and have the same coordinates. The <g>
element is by default positioned at (0, 0) — the top-left of the viewBox. This is true for all SVG elements.
The <line>
elements have similar values of x1, y1, x2 and y2 so that they are of the same height.
CSS
Move <g>
element to the center and rotate the lines in intervals of 30 degrees to make them equally spaced around the clock. Let’s also make the 3, 6, 9 and 12 hour marks thicker than the rest by setting theirstroke-width
to 0.5
and for the rest of the hands to 0.2
.
Let’s add the moving hands and a pin that holds them in place.
HTML
The order of these elements matters. It affects their z-index. Elements that come later in the DOM appear above those that come before them.
CSS
Move the hands of the clock to the center and give them different values of stroke-width
to distinguish them.
This is the output of the code we have written so far.
From the image above, you can see that the hands are pointing at the 3 O’clock mark (at a rotate(0deg)
). Let’s move the hands to the 12 O’clock mark by rotating the entire SVG by -90deg
(-ve degrees rotate anti-clockwise).
CSS
Add the following CSS properties to the svg
element to make the hands point to the 12 O’clock mark.
svg {
...
transform: rotate(-90deg);
}
Add some text (for branding purposes) that says, “#TIA” — This is Andela.
HTML
Add the following mark up before the line
elements that draw the hands to make it appear below the hands.
<text x="0" y="0" class="tiaText">#TIA</text>
CSS
Position and style the text above.
.tiaText {
font-size: 1px;
font-family: sans-serif;
transform: translate(14px, 19px) rotate(90deg);
fill: #dfdfdf;
stroke: none;
}
This is what your clock should look like if everything is done right. :)
What’s a clock that doesn’t tick? — A dead clock. Let’s make ours work.
Section 2 — Making the clock work.
In order for us to pull off this job, we’re going to employ CSS variables.
Add some CSS variables to reference the time when the page loads. Add the following CSS variables to the svg
element’s selector.
svg {
...
--start-seconds: 57;
--start-minutes: 45;
--start-hours: 11;
}
Make the hands correctly indicate the time set above.
CSS
Let’s use CSS transforms to position the hands to the center and rotate them to indicate the appropriate seconds, minutes, or hours set above.
Formula: (Number of seconds/minutes) * 6degrees = rotation of the respective hand for both the seconds and minutes hands.
The clock can only indicate 12 hours so we multiply the number of hours by 30degrees to compute the rotation of the hour hand.
CSS
To make the seconds hand work, we shall define an animation called rotateSecondsHand
and use it on the seconds hand (.seconds
). The animation timing function is steps(60)
.
To make the minute hand work, we shall define an animation called rotateMinuteHand
and use it on the minute hand (.minute
).
CSS
The animation timing function is steps(60)
. We need to set the animation-delay
to a negative value based on the value of --start-seconds
. We do this to “forward” the animation, so that the minute hand moves whenever the seconds hand reaches the 12 O’clock mark.
Finally, let’s make the hour hand work. Note that for the hour hand (.hour
), animation-delay
is dependent on --start-seconds
and --start-minutes
.
CSS
Here the animation delay is dependent on the values of --start--seconds
& --start-minutes
.
How to test the clock.
- To test the minute hand, set
--start--seconds:59
,--start-minutes:59
and--start-hours:11
. The minute hand should move one step with the seconds hand and stop. After that, the minute hand should move whenever the seconds hand reaches the 12 hour mark. - To test the hour hand, set
--start--seconds:30
,--start-minutes:30
and--start-hours:11
. The hour hand should be midway between the 11 and 12 O’clock marks.
Final thoughts
Until CSS can enable us to tell time, we need JavaScript to set the correct time. The accuracy of this clock will depend on that of your device’s time. Here is the JavaScript code that does the job.
This is still a pure CSS clock because it’s functionality is completely in written CSS.
Thanks for making it to the end of the tutorial. If you feel I have left out some explanation(s), feel free to engage me in a discussion via the comments.