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.
A 3×3×3 wireframe: three layers of bars and glowing nodes, and nine posts through them. The outer layers move apart while the posts stretch by the same amount, so no joint ever opens.
Your edited version
::after turned rotateX(90deg) around the bar's own length.rotateY(90deg), standing up with rotateZ(90deg). --x, --y, --z (−1, 0 or 1) times the spacing place it.translateY(y × 1.3 × step): the middle one has y = 0, so the same keyframes leave it in place.scaleY(1.3) on the same beat, so the posts stretch by exactly what the layers move and no joint ever opens.--u, tied to the canvas, so the lattice is the same share of a gallery card, the editor and a recording canvas. The spacing, --step, is 50 of those units, and the lattice is sized for its fullest breath.rotateY(-360deg), same timing), so they always face you.bars as two crossed planeslayers: translateY(y × distance)posts: scaleY in step with the layersbillboard nodes<div class="scene">
<div class="lattice">
<div class="layer" style="--y:-1">
<i style="--z:-1"></i>
<i style="--z:0"></i>
<i style="--z:1"></i>
<i class="z" style="--x:-1"></i>
<i class="z" style="--x:0"></i>
<i class="z" style="--x:1"></i>
<b style="--x:-1; --z:-1"></b>
<b style="--x:0; --z:-1"></b>
<b style="--x:1; --z:-1"></b>
<b style="--x:-1; --z:0"></b>
<b style="--x:0; --z:0"></b>
<b style="--x:1; --z:0"></b>
<b style="--x:-1; --z:1"></b>
<b style="--x:0; --z:1"></b>
<b style="--x:1; --z:1"></b>
</div>
<div class="layer mid" style="--y:0">
<i style="--z:-1"></i>
<i style="--z:0"></i>
<i style="--z:1"></i>
<i class="z" style="--x:-1"></i>
<i class="z" style="--x:0"></i>
<i class="z" style="--x:1"></i>
<b style="--x:-1; --z:-1"></b>
<b style="--x:0; --z:-1"></b>
<b style="--x:1; --z:-1"></b>
<b style="--x:-1; --z:0"></b>
<b style="--x:0; --z:0"></b>
<b style="--x:1; --z:0"></b>
<b style="--x:-1; --z:1"></b>
<b style="--x:0; --z:1"></b>
<b style="--x:1; --z:1"></b>
</div>
<div class="layer" style="--y:1">
<i style="--z:-1"></i>
<i style="--z:0"></i>
<i style="--z:1"></i>
<i class="z" style="--x:-1"></i>
<i class="z" style="--x:0"></i>
<i class="z" style="--x:1"></i>
<b style="--x:-1; --z:-1"></b>
<b style="--x:0; --z:-1"></b>
<b style="--x:1; --z:-1"></b>
<b style="--x:-1; --z:0"></b>
<b style="--x:0; --z:0"></b>
<b style="--x:1; --z:0"></b>
<b style="--x:-1; --z:1"></b>
<b style="--x:0; --z:1"></b>
<b style="--x:1; --z:1"></b>
</div>
<div class="posts">
<i style="--x:-1; --z:-1"></i>
<i style="--x:0; --z:-1"></i>
<i style="--x:1; --z:-1"></i>
<i style="--x:-1; --z:0"></i>
<i style="--x:0; --z:0"></i>
<i style="--x:1; --z:0"></i>
<i style="--x:-1; --z:1"></i>
<i style="--x:0; --z:1"></i>
<i style="--x:1; --z:1"></i>
</div>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the lattice is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.3vmin;
perspective: calc(800 * var(--u));
}
.lattice {
--step: calc(50 * var(--u)); /* the spacing between nodes */
position: relative;
width: 0;
height: 0;
transform-style: preserve-3d;
animation: spin 18s linear infinite;
}
.layer,
.posts {
position: absolute;
transform-style: preserve-3d;
}
.layer {
transform: translateY(calc(var(--y) * var(--step)));
animation: breathe 2.4s ease-in-out infinite alternate;
}
.posts {
animation: stretch 2.4s ease-in-out infinite alternate;
}
/* a bar along X, two crossed planes */
.lattice i {
position: absolute;
top: calc(-1 * var(--u));
left: calc(var(--step) * -1);
width: calc(var(--step) * 2);
height: calc(2 * var(--u));
transform-style: preserve-3d;
background: linear-gradient(90deg, #2ee6d6, rgb(139 108 255 / 0.85) 30% 70%, #2ee6d6);
transform: translateZ(calc(var(--z) * var(--step)));
}
.lattice i::after {
content: '';
position: absolute;
inset: 0;
background: inherit;
transform: rotateX(90deg);
}
/* the same bar along Z */
.lattice i.z {
transform: translateX(calc(var(--x) * var(--step))) rotateY(90deg);
}
/* and standing up */
.posts i {
transform: translateX(calc(var(--x) * var(--step))) translateZ(calc(var(--z) * var(--step))) rotateZ(90deg);
}
.lattice b {
--glow: 46 230 214;
position: absolute;
top: calc(-6 * var(--u));
left: calc(-6 * var(--u));
width: calc(12 * var(--u));
height: calc(12 * var(--u));
border-radius: 50%;
background: radial-gradient(circle, color-mix(in srgb, rgb(var(--glow)) 25%, #fff) 0 22%, rgb(var(--glow)) 42%, rgb(var(--glow) / 0) 72%);
animation: face-you 18s linear infinite;
}
.mid b { --glow: 255 77 157; }
.mid b:nth-of-type(5) { --glow: 255 181 71; } /* the very centre */
@keyframes spin {
from { transform: rotateZ(-8deg) rotateX(-22deg) rotateY(0deg); }
to { transform: rotateZ(-8deg) rotateX(-22deg) rotateY(360deg); }
}
/* y = 0 for the middle layer, so it stays put */
@keyframes breathe {
to { transform: translateY(calc(var(--y) * var(--step) * 1.3)); }
}
/* (step + 0.3 step) / step: exactly what the outer layers moved */
@keyframes stretch {
to { transform: scaleY(1.3); }
}
@keyframes face-you {
from { transform: translate3d(calc(var(--x) * var(--step)), 0, calc(var(--z) * var(--step))) rotateY(0deg); }
to { transform: translate3d(calc(var(--x) * var(--step)), 0, calc(var(--z) * var(--step))) rotateY(-360deg); }
}