Twisting puzzle cube
Pure CSSA 3×3×3 cube built as three layers that take turns twisting a quarter turn. Each layer is one flat box with the stickers painted on by gradients.
Sixteen cubes seen isometrically, rising and falling in a wave that travels along the diagonals. Each cube is one element: its top plus two folded pseudo-element sides.
Your edited version
rotateZ(-45deg), then tip it back with rotateX. "Up" is now the grid's own Z axis, so translateZ lifts a cube straight off the floor.::before / ::after are the sides, hinged on its edges and folded down.--d is row + column, so cubes on the same diagonal share a delay and the wave travels corner to corner.transform animates, so 16 cubes stay cheap.--u, tied to the canvas: a cube is 36 units, and the wave lifts it 44. The field is the same share of a gallery card, the editor and a recording canvas.rotateX + rotateZ isometric flooronly the two visible sides, as ::before / ::aftertranslateZ along the floor normaldelay = (row + column) × step<div class="scene">
<div class="field">
<i style="--d:0"></i>
<i style="--d:1"></i>
<i style="--d:2"></i>
<i style="--d:3"></i>
<i style="--d:1"></i>
<i style="--d:2"></i>
<i style="--d:3"></i>
<i style="--d:4"></i>
<i style="--d:2"></i>
<i style="--d:3"></i>
<i style="--d:4"></i>
<i style="--d:5"></i>
<i style="--d:3"></i>
<i style="--d:4"></i>
<i style="--d:5"></i>
<i style="--d:6"></i>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the field is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.34vmin;
perspective: calc(800 * var(--u));
}
.field {
display: grid;
grid-template-columns: repeat(4, calc(36 * var(--u)));
gap: calc(10 * var(--u));
transform-style: preserve-3d;
/* isometric floor: turn 45deg, then tip back. The cube sides fold down below the floor and the
near corner is magnified, so what the field paints hangs below its layout box even with the
wave lifting the cubes: the floor is raised that much and the whole field stays centred. */
transform: translateY(calc(-8 * var(--u))) rotateX(58deg) rotateZ(-45deg);
}
/* the element itself is the top of the cube */
.field i {
--hue: calc(253 - var(--d) * 13); /* violet corner to teal corner */
position: relative;
width: calc(36 * var(--u));
height: calc(36 * var(--u));
background: hsl(var(--hue) 90% 80%);
transform-style: preserve-3d;
animation: wave 2.6s ease-in-out infinite;
animation-delay: calc(var(--d) * -0.28s);
}
.field i::before,
.field i::after {
content: '';
position: absolute;
}
/* side hinged on the bottom edge, folded down */
.field i::before {
left: 0;
top: 100%;
width: 100%;
height: calc(36 * var(--u));
background: hsl(var(--hue) 85% 64%);
transform-origin: top;
transform: rotateX(-90deg);
}
/* side hinged on the left edge, folded down */
.field i::after {
right: 100%;
top: 0;
width: calc(36 * var(--u));
height: 100%;
background: hsl(var(--hue) 55% 36%);
transform-origin: right;
transform: rotateY(-90deg);
}
@keyframes wave {
0%, 100% { transform: translateZ(0); }
50% { transform: translateZ(calc(44 * var(--u))); }
}