# TL;DR;

See the Pen Lumenaki Loader by Khanh Hua (@khanhhua) on CodePen.

# Long Story

## Skills involved

- CSS3 animation
- CSS3 transform
- Basic geometry and math
- Patience

## How to build

### The HTML structure

```
.loader
.quadrant
.quadrant-sub
span
.quadrant-sub
span
.quadrant
.quadrant-sub
span
.quadrant-sub
span
.quadrant
.quadrant-sub
span
.quadrant-sub
span
.quadrant
.quadrant-sub
span
.quadrant-sub
span
```

You may want to use `.quadrant-sub:after`

to create pseudo elements instead of `span`

. Anyways, let us analyze the structure. As you have observed:

- The indicator rotates about its center
- The diamonds rotate about 2 axes: one diagonal and its center
- Each diamond has two separate sub-parts, only one of the two is visible at a time.

There is a reason behind the aforementioned structure. We will discuss after we explore the CSS declarations.

### CSS

The most interesting aspect would be keyframe definitions for rotations. Each DOM (loader, quadrant and subpart) needs to associate with one and only animation, one and only one transformation.

- The loader (
`.loader`

)

```
@keyframes ani-loader {
0% {
transform: rotate(0deg);
}
69% {
transform: rotate(0deg);
}
100% {
transform: rotate(90deg);
}
}
```

- The sub-parts (
`.quadrant-sub`

)

```
@keyframes ani-quad1-ne {
0% {
transform: rotate3d(-1,1,0,0deg);
}
20% {
transform: rotate3d(-1,1,0,0deg);
}
44% {
transform: rotate3d(-1,1,0,90deg);
}
100% {
transform: rotate3d(-1,1,0,90deg);
}
}
@keyframes ani-quad1-nw {
0% {
transform: rotate3d(1,1,0,90deg);
}
44% {
transform: rotate3d(1,1,0,90deg);
}
55% {
transform: rotate3d(1,1,0,0deg);
}
100% {
transform: rotate3d(1,1,0,0deg);
}
}
```

- The quadrants (
`.quadrant`

)

```
@keyframes ani-quad1-rotate {
0% {
transform: rotate(0deg);
}
52% {
transform: rotate(0deg);
}
69% {
transform: rotate(90deg);
}
100% {
transform: rotate(90deg);
}
}
```

I have shown this crystal loader to a few interviewees and colleagues. Most of them assumed an over simplistic solution in terms of both CSS and HTML structure. The common mistake is how the animated property `transform`

is understood. In my solution, there are 13 `keyframes`

definitions while the often proposed figure is 4. To animate this loader, we need:

- 1
`keyframes`

definition for the entire block - 4
`keyframes`

definitions for the`.quadrant`

- 8
`keyframes`

definitions for the`.quadrant-sub`

The take-away point is that CSS matrix transformation is basically an application of **linear** algebra. By **linear**, it means each point of our DOM elements is converted from its original position to the final destination. No matter how many `translate`

, `rotate`

, `scale`

and `skew`

you may apply for the transform property, browser will calculate one and only one `matrix`

which represents the entire transformation. During animation/transition, the final destination is recalculated based on the original position - NOT the previously calculated value using this `matrix`

.

Put that altogether, we now understand how this loader works:

- To produce the diamond, one
`matrix`

is used for the`.quadrant-sub span`

s. - To make the diamond flip around the diagonal, one
`matrix`

* is applied for`.quadrant-sub`

. - To make the diamond rotate around its center, one
`matrix`

* is applied for the`.quadrant`

s. Their children are rotated also. - To make the whole block rotate, one
`matrix`

* is applied for the`.loader`

.

*`matrix`

value is an interpolated figure.

In other words, you *cannot* make **the diamonds, by themselves, distorted and animated at the same time**. You have to wrap them as many levels as the number of concurrent `matrix`

values are used.

# Your assignment

Can you make this Lumenaki Crystal Loader adapt to various sizes? How about making the loader fluid?

See Lumenaki - album 209 for the piece of code in production.