Draw and Animate a Diamond Using CSS Only

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 theoverflow: visible property.

.wrap {
  position:absolute;
  width:0px;
  height:0px;
  top:50%; 
  left:50%;
  transform-origin:0 0;
  transform-style: preserve-3d;
  overflow:visible; 
}
1
2
3
4
5
6
7
8
9
10

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>
1
2
3
4
5
6
7

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); }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

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;
}
1
2
3
4
5
6
7
8
9
10
11

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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

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 ...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

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 ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Source Code

¡And... Voilà!

Checkout the full source here

Join The Conversation