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 glass tube with rings of light rising inside. CSS has no curves in 3D, so the tube is 24 flat strips, each 2r × tan(180° / 24) wide.
Your edited version
--u, so the tube is the same share of a gallery card, the editor and a recording canvas. The numbers below are those units.2 × r × tan(180° / n). For r = 80 and n = 24 that is ≈ 21; add 1 so no seams show.rotateY(i × 15deg) translateZ(r). Semi-transparent strips let the far side show through, which is what makes it read as glass.rotateX(90deg). They rise by animating translate, which is applied before transform, so "up" is the tube's own vertical.strip width = 2r × tan(180° / n)rotateY + translateZper-strip shading<div class="scene">
<div class="cylinder">
<i style="--i:0"></i>
<i style="--i:1"></i>
<i style="--i:2"></i>
<i style="--i:3"></i>
<i style="--i:4"></i>
<i style="--i:5"></i>
<i style="--i:6"></i>
<i style="--i:7"></i>
<i style="--i:8"></i>
<i style="--i:9"></i>
<i style="--i:10"></i>
<i style="--i:11"></i>
<i style="--i:12"></i>
<i style="--i:13"></i>
<i style="--i:14"></i>
<i style="--i:15"></i>
<i style="--i:16"></i>
<i style="--i:17"></i>
<i style="--i:18"></i>
<i style="--i:19"></i>
<i style="--i:20"></i>
<i style="--i:21"></i>
<i style="--i:22"></i>
<i style="--i:23"></i>
<b></b><s></s>
<u></u><u></u><u></u>
</div>
</div>
.scene {
/* one base unit: every length below is a multiple of it, so the tube is the same share of a
card, the editor, a full screen and a recording canvas */
--u: 0.24vmin;
perspective: calc(800 * var(--u));
}
.cylinder {
--r: calc(80 * var(--u));
--h: calc(180 * var(--u));
position: relative;
width: calc(22 * var(--u)); /* 2 × 80 × tan(7.5deg) + 1 */
height: var(--h);
transform-style: preserve-3d;
animation: cylinder-spin 14s linear infinite;
}
/* see-through strips: the far side of the tube shows through the near one */
.cylinder i {
position: absolute;
inset: 0;
background:
linear-gradient(rgb(255 255 255 / 0.55) 0 calc(2 * var(--u)), transparent calc(2 * var(--u)) calc(100% - 2 * var(--u)), rgb(255 255 255 / 0.4) calc(100% - 2 * var(--u))),
linear-gradient(hsl(calc(170 + var(--i) * 6) 85% 62% / 0.5), hsl(calc(250 + var(--i) * 3) 80% 58% / 0.14));
transform: rotateY(calc(var(--i) * 15deg)) translateZ(var(--r));
}
/* lid (b) and floor (s): glass discs laid flat */
.cylinder b,
.cylinder s {
position: absolute;
left: calc(50% - var(--r));
width: calc(var(--r) * 2);
height: calc(var(--r) * 2);
box-sizing: border-box;
border: calc(1 * var(--u)) solid rgb(255 255 255 / 0.4);
border-radius: 50%;
background: radial-gradient(circle, rgb(255 255 255 / 0.16), rgb(139 108 255 / 0.22) 70%);
transform: rotateX(90deg);
}
.cylinder b { top: calc(var(--r) * -1); }
.cylinder s {
top: calc(var(--h) - var(--r));
box-shadow: 0 0 calc(40 * var(--u)) rgb(46 230 214 / 0.55);
}
/* rings of light rising through the tube. `translate` moves them up the tube's own vertical,
before the rotateX that lays them flat. */
.cylinder u {
position: absolute;
top: calc(var(--h) - var(--r) + 8 * var(--u));
left: calc(50% - var(--r) + 8 * var(--u));
width: calc(var(--r) * 2 - 16 * var(--u));
height: calc(var(--r) * 2 - 16 * var(--u));
box-sizing: border-box;
border: calc(2 * var(--u)) solid #2ee6d6;
border-radius: 50%;
box-shadow: 0 0 calc(14 * var(--u)) #2ee6d6, inset 0 0 calc(14 * var(--u)) #2ee6d6;
opacity: 0;
transform: rotateX(90deg);
animation: rise 3.6s linear infinite;
}
.cylinder u:nth-of-type(2) { animation-delay: -1.2s; }
.cylinder u:nth-of-type(3) { animation-delay: -2.4s; }
@keyframes cylinder-spin {
from { transform: rotateX(-20deg) rotateY(0deg); }
to { transform: rotateX(-20deg) rotateY(360deg); }
}
@keyframes rise {
0% { opacity: 0; translate: 0 calc(-4 * var(--u)); }
15%, 80% { opacity: 1; }
100% { opacity: 0; translate: 0 calc(var(--h) * -1 + 12 * var(--u)); }
}