The animation below was created without any JavaScript and only using HTML elements and CSS properties.
The Container
First let’s create a container CSS class that will contain the diamond elements. Because we’re going to be rotating the elements in a 3D space, we define the center of rotation in the middle/center of the area. The idea here is to center the element vertically and horizontally while maintaining objects visible using the overflow: visible
property.
.wrap {
position: absolute;
width: 0px;
height: 0px;
top: 50%;
left: 50%;
transform-origin: 0 0;
transform-style: preserve-3d;
overflow: visible;
}
Next we create the HTML container element, or better say the containers.
<div class="wrap rotor-x">
<div class="wrap rotor-y">
<div class="wrap rotor-z">...</div>
</div>
</div>
Notice how we need one container for each axis of rotation. This demo actually only uses X and Y axis but for the sake of 3D joy, we also add support for rotation around the Z axis.
Next, we use CSS to set and/or animate these axes of rotation.
.rotor-x {
transform: rotateX(-22deg);
}
.rotor-y {
animation: spinY 12s infinite linear;
}
@keyframes spinX {
from {
transform: rotateX(0);
}
to {
transform: rotateX(360deg);
}
}
@keyframes spinY {
from {
transform: rotateY(0);
}
to {
transform: rotateY(360deg);
}
}
Triangles
Now let’s create a .triangle
class that will be applied to every single face of the diamond. These faces are also referred here as triangles.
.triangle {
position: absolute;
left: -100px;
top: -50px;
width: 0;
height: 0;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
border-bottom: 100px solid #33afff;
animation: lighting 12s infinite linear;
}
Once our class is ready we add the triangles to our containers as below:
<div class="wrap rotor-x">
<div class="wrap rotor-y">
<div class="wrap rotor-z">
<div class="triangle bottom face-1"></div>
<div class="triangle bottom face-2"></div>
<div class="triangle bottom face-3"></div>
<div class="triangle bottom face-4"></div>
<div class="triangle bottom face-5"></div>
etc ...
</div>
</div>
</div>
And now the most tedious part, we need to position each triangle in a 3D space to create a diamond:
/** Bottom Down **/
.triangle.bottom {
transform-origin: 50% 0%; }
.triangle.bottom.face-1 {
transform: translateY(90px) rotateY(0deg) rotateX(35deg) scaleX(.24) scaleY(-1) ; }
.triangle.bottom.face-2 {
transform: translateY(90px) rotateY(45deg) rotateX(35deg) scaleX(.24) scaleY(-1) ; }
.triangle.bottom.face-3 {
transform: translateY(90px) rotateY(90deg) rotateX(35deg) scaleX(.24) scaleY(-1) ; }
.triangle.bottom.face-4 {
transform: translateY(90px) rotateY(135deg) rotateX(35deg) scaleX(.24) scaleY(-1) ; }
.triangle.bottom.face-5 {
transform: translateY(90px) rotateY(180deg) rotateX(35deg) scaleX(.24) scaleY(-1) ; }
etc ...
And so on…
Taking it further
Because we’re actually not using any lighting system or normals, we add a cheap trick to simulate reflection by adding random blinking animations to the tiangles, and apply different delays to prevent duplicates.
/* Create blinking animation loops */
@keyframes lighting {
0% { border-bottom-color:#33AFFF; }
50% { border-bottom-color:#BBE8FF; }
100% { border-bottom-color:#33AFFF; }
}
@keyframes lighting-lighter {
0% { border-bottom-color:#72C8FF; }
50% { border-bottom-color:#99EAFF; }
100% { border-bottom-color:#72C8FF; }
}
/* Apply them to the triangle with various delay values */
.triangle.up {
animation: lighting-lighter 12s infinite linear;
.triangle.up.face-1 {
animation-delay: -3500ms;
.triangle.up.face-2 {
animation-delay: -4500ms;
etc ...
Source Code
¡And… Voilà!
Checkout the full source here