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.
Eight triangles hinged on a square equator, leaning in by 35.26° so they meet at two apexes. One rule builds all of them: scaleY(-1) flips the bottom four.
Your edited version
clip-path), standing on one edge of the square "equator".--u, so the solid is the same share of a gallery card, the editor and a recording canvas.transform-origin: 50% 100%) and lean it in by 90° − atan(√2) ≈ 35.26°: exactly enough for four tips to meet on the axis.--s: -1 flips the triangle to point down with scaleY(-1) and reverses the lean, so one line of CSS builds all eight faces.clip-path also clips borders away, so the slanted edges are painted: a to top left gradient's 50% line runs exactly along its box diagonal.clip-path triangleslean = 90° − atan(√2)--s: 1 / −1 flips half the facesedges drawn with "to corner" gradients<div class="scene">
<div class="octa">
<i style="--i:0; --s:1"></i>
<i style="--i:1; --s:1"></i>
<i style="--i:2; --s:1"></i>
<i style="--i:3; --s:1"></i>
<i style="--i:0; --s:-1"></i>
<i style="--i:1; --s:-1"></i>
<i style="--i:2; --s:-1"></i>
<i style="--i:3; --s:-1"></i>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the solid is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.41vmin;
perspective: calc(800 * var(--u));
}
.octa {
--a: calc(110 * var(--u)); /* edge length */
position: relative;
width: var(--a);
height: var(--a);
transform-style: preserve-3d;
animation: spin 12s linear infinite;
}
.octa i {
--c: 139 108 255;
--alpha: 0.22;
--edge: rgb(var(--c) / 0.85);
position: absolute;
left: 0;
bottom: 50%; /* bottom edge on the equator, through the centre */
width: var(--a);
height: calc(95.26 * var(--u)); /* triangle height = a × √3 / 2 */
transform-origin: 50% 100%;
transform:
rotateY(calc(var(--i) * 90deg))
translateZ(calc(var(--a) / 2))
rotateX(calc(var(--s) * 35.26deg)) /* lean in: 90deg - atan(√2) */
scaleY(var(--s)); /* -1 flips the bottom four downward */
clip-path: polygon(50% 0, 0 100%, 100% 100%);
background:
linear-gradient(to top left, transparent calc(50% - 1.5 * var(--u)), var(--edge) calc(50% - 1.5 * var(--u)) 50%, transparent 50%) left / 50% 100% no-repeat,
linear-gradient(to top right, transparent calc(50% - 1.5 * var(--u)), var(--edge) calc(50% - 1.5 * var(--u)) 50%, transparent 50%) right / 50% 100% no-repeat,
linear-gradient(var(--edge), var(--edge)) bottom / 100% calc(1.5 * var(--u)) no-repeat,
linear-gradient(to top, rgb(var(--c) / var(--alpha)), rgb(var(--c) / 0.08));
}
.octa i:nth-child(n + 5) {
--c: 46 230 214;
}
/* checkerboard the brightness so neighbouring faces always differ */
.octa i:nth-child(-n + 4):nth-child(odd),
.octa i:nth-child(n + 5):nth-child(even) {
--alpha: 0.42;
}
@keyframes spin {
from { transform: rotateZ(14deg) rotateX(-16deg) rotateY(0deg); }
to { transform: rotateZ(14deg) rotateX(-16deg) rotateY(360deg); }
}