3D CSS animation flip down clock, with minimal JavaScript

Roman Balitsky
JavaScript developer
Mon Mar 20 2023
CSS in HTML provides opportunity for some nice transformations. One of such is an ability to create basic 3D transformations with a perspective and apply an animation to them. Here we are looking at using such transformation and a basic animation with minimal use of JavaScript, relying for smoothness on CSS as much as possible.
To achieve that effect two things are happening here: the rotating slots have a CSS property transform calling rotateX(...) function:
transform: rotateX(...);
... and the containing element sets a transform perspective and a 3D transformation style (otherwise the rotation appears flat):
transform: perspective(500px);
transform-style: preserve-3d;
For every slot there are two rotating elements: one is for the top half of the number that is disappearing and the other is the lower half of the number that is emerging. The first number is the "front" and the other is the "back". The front starts the animation upright and the back starts up side down.
front
1
2
back
By default HTML elements rotate around their center, to change that we are using transform-origin property to set the rotation point along the edge. Therefore their transform-origin properties are as following:
transform-origin: bottom center;
... for the front, and for the back:
transform-origin: top center;
In addition to the actual 3D effect, the rotating slots have their background color change to imitate the light and shading. Background animation for the front side:
@keyframes ... {
    0% { background-color: grey }
  100% { background-color: black }
}
And the same for the back side:
@keyframes ... {
    0% { background-color: white }
  100% { background-color: grey }
}
Although one animation ends at full black and the other starts at full white, the user only gets to see the first half of the front side animation, and the second half of the back side animation. Therefore they never get to see any actually black or white background.
The complete slot is made of four parts: two static halves and two rotating halves (previously known as front and back). Following is the full HTML code for a slot. Note the emerging and disappearing variables. Emerging is the number to be displayed and disappearing is the number displayed previously. Each number is presented by it's two respectful halves: upper and lower.
<!-- Upper half of the slot. Static (not rotating). -->
<div class="a-half">
  <div class="number-upper-half">${emerging}</div>
</div>

<!-- Front of the rotating slot -->
<div class="rotation-basis">
  <div class="a-half rotating-half-front-side">
    <div class="number-upper-half">${disappearing}</div>
  </div>
</div>

<!-- Back of the rotating slot -->
<div class="rotation-basis">
  <div class="a-half rotating-half-back-side">
    <div class="number-lower-half">${emerging}</div>
  </div>
</div>

<!-- Lower half of the slot. Static (not rotating). -->
<div class="a-half">
  <div class="number-lower-half">${disappearing}</div>
</div>
An interval timer is executed every second. And for every slot which value is meant to change, the entire HTML code for it is replaced. This is the easiest way to restart animation for the rotating halves.
Below is a full source code for the clock. It is hosted on the Chatium platform. Opening this page on your computer allows to play with the source code and see the result of any change in real time.