In my previous related post, i sent an emoji to a round trip using CSS motion path. In this post, i will build a clock using the motion path css properties and some Javascript.

Initial setup

To build a clock, we need a circle and 12 numbers as a clock face. Lets start with the circle.

.clock {
    width: 400px;
    height: 400px;
    border: 2px solid #569092;
    border-radius: 50%;
    margin: auto;
}

Here is how it looks.

The clock face is a circle with a radius of 50%. Lets add the nubmers now. We’ll start with 12 and place it where it should be.

.digit {
    width: 50px;
    height: 50px;
    background-color: black;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 2rem;
    color: white;
}

Here is how it looks.

12

Using the offset properties (learned in part 1), we can position the numbers along the circle. Lets do it step by step. Lets add a new style per number:

.twelve {
    offset-path: ray(0deg);
}
12

Here i have used the ray() function to define the offset path. As per the motion path speces, the ray function is used to position an element along an angle and a distance. The ray function takes two parameters, the first is the angle and the second is the size of the ray. Here we will use the just the first parameter to position the element along the angle. When we use the ray function, the anchor of the element shifts to the center of the parent element. So to place the number on the circumference, we need to use offset-distance: 85%. Also since the rotation of the number is off, we need to set the offset-rotate property to 0deg.

.digit {
    ....
    offset-path: ray(0deg);
    offset-distance: 85%;
}
12

Now we can position the numbers on the circumference by setting the respective angles for the ray() function. Lets add the following styles:

.one {
    offset-path: ray(30deg);
}

.two {
    offset-path: ray(60deg);
}

.three {
    offset-path: ray(90deg);
}

....

.eleven {
    offset-path: ray(330deg);
}
12
1
2
3
4
5
6
7
8
9
10
11

Setting up the hands

Now that we have positioned the numbers on the circumference, we can position the hands. Lets add 3 divs for the hands and add the following styles:

.hand {
    width: 4px;
    height: 40%;
    border-radius: 4px;
    background-color: black;
    offset-path: ray(0deg);
    offset-anchor: bottom;
}

.seconds {
    offset-rotate: 0deg;
}

.minutes {
    offset-rotate: 30deg;
}

.hours {
    offset-rotate: 60deg;
    height: 25%;
}
12
1
2
3
4
5
6
7
8
9
10
11

We have our clock ready. Now lets add the following styles and javascript to get it ticking. We will use the css variables to update the angle of the hands.

:root {
    --seconds: 0deg;
    --minutes: 0deg;
    --hours: 0deg;
}

.seconds {
    ....
    offset-rotate: var(--seconds);
}

.minutes {
    ....
    offset-rotate: var(--minutes);
}

.hours {
    ....
    offset-rotate: var(--hours);
}
<script>
    const secondsHand = document.querySelector('.seconds');
    const minutesHand = document.querySelector('.minutes');
    const hoursHand = document.querySelector('.hours');

    setInterval(() => {
        const now = new Date();
        const hours = now.getHours();
        const minutes = now.getMinutes();
        const seconds = now.getSeconds();
        // minutesDelta is the exact number of degrees to rotate the minute hand
        const minutesDelta = (minutes * 6) + (seconds * 0.1);
        // hoursDelta is the exact number of degrees to rotate the hour hand
        const hoursDelta = (hours * 30) + (minutes * 0.5);
        
        hoursHand.style.setProperty('--hours', `${hoursDelta}deg`);
        minutesHand.style.setProperty('--minutes', `${minutesDelta}deg`);
        secondsHand.style.setProperty('--seconds', `${seconds * 6}deg`);
    }, 1000);
</script>

And we have a ticking clock!!!

12
1
2
3
4
5
6
7
8
9
10
11

Hurray!!! Let your imagination go wild and build some cool things with CSS motion path.