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.
Five hexagonal prisms of different sizes growing from one rock at different tilts. Each side panel carries its own tip facet as a ::before, folded in so the six meet in a point.
Your edited version
--w wide in a closed ring, rotateY(i × 60deg) translateZ(w × 0.866). 0.866 is √3 / 2, the apothem of a hexagon with side w.::before. The panel gets transform-style: preserve-3d, so the triangle can fold in along the panel's top edge by 40°. Its height, apothem / sin(40°) = 1.347 × w, makes the six points meet on the axis.rotateY to face its direction, translateZ out from the centre, then rotateX to lean outward. The same four numbers in a style attribute place all five.opacity would flatten its 3D children.hexagon ring: apothem = side × √3 / 2tip facet as a folded ::beforerotateY · translateZ · rotateX to lean outcrossed glow planes<div class="scene">
<div class="cluster">
<b class="rock"></b>
<div class="crystal" style="--az:0deg; --off:0px; --tilt:0deg; --w:22px; --h:86px; --c:#8b6cff; --c2:#ff4d9d; --d:0s">
<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>
<b></b>
</div>
<div class="crystal" style="--az:30deg; --off:16px; --tilt:30deg; --w:15px; --h:60px; --c:#2ee6d6; --c2:#8b6cff; --d:-1.2s">
<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>
<b></b>
</div>
<div class="crystal" style="--az:115deg; --off:14px; --tilt:26deg; --w:14px; --h:50px; --c:#ff4d9d; --c2:#8b6cff; --d:-2.4s">
<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>
<b></b>
</div>
<div class="crystal" style="--az:205deg; --off:16px; --tilt:34deg; --w:16px; --h:66px; --c:#8b6cff; --c2:#2ee6d6; --d:-0.6s">
<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>
<b></b>
</div>
<div class="crystal" style="--az:290deg; --off:14px; --tilt:30deg; --w:12px; --h:40px; --c:#2ee6d6; --c2:#ff4d9d; --d:-3s">
<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>
<b></b>
</div>
</div>
</div>
.scene {
perspective: 800px;
}
.cluster {
position: relative;
width: 0;
height: 0;
transform-style: preserve-3d;
animation: spin 30s linear infinite;
}
/* stand on the floor (44px down), face a direction, step out, lean outward */
.crystal {
position: absolute;
transform-style: preserve-3d;
transform: translateY(44px) rotateY(var(--az)) translateZ(var(--off)) rotateX(calc(var(--tilt) * -1));
}
/* six side panels in a closed ring */
.crystal i {
position: absolute;
top: calc(var(--h) * -1);
left: calc(var(--w) / -2);
width: var(--w);
height: var(--h);
transform-style: preserve-3d; /* lets the tip fold in 3D */
transform: rotateY(calc(var(--i) * 60deg)) translateZ(calc(var(--w) * 0.866));
background:
linear-gradient(90deg, transparent 30%, rgb(255 255 255 / 0.2) 42%, transparent 54%),
linear-gradient(to top, color-mix(in srgb, var(--c) 62%, transparent), color-mix(in srgb, var(--c) 14%, transparent) 70%, color-mix(in srgb, var(--c) 28%, transparent));
box-shadow:
inset 1px 0 color-mix(in srgb, var(--c) 80%, transparent),
inset -1px 0 color-mix(in srgb, var(--c) 80%, transparent),
inset 0 1px color-mix(in srgb, var(--c) 85%, #fff);
}
.crystal i:nth-child(even) {
--c: var(--c2);
}
/* the tip facet: hinged on the panel's top edge, folded in by 40deg */
.crystal i::before {
--edge: color-mix(in srgb, var(--c) 85%, #fff);
content: '';
position: absolute;
bottom: 100%;
left: 0;
width: 100%;
height: calc(var(--w) * 1.347); /* apothem / sin(40deg) */
transform-origin: 50% 100%;
transform: rotateX(40deg);
clip-path: polygon(50% 0, 0 100%, 100% 100%);
background:
linear-gradient(to top left, transparent calc(50% - 1px), var(--edge) calc(50% - 1px) 50%, transparent 50%) left / 50% 100% no-repeat,
linear-gradient(to top right, transparent calc(50% - 1px), var(--edge) calc(50% - 1px) 50%, transparent 50%) right / 50% 100% no-repeat,
linear-gradient(color-mix(in srgb, var(--c) 20%, #fff 30%), color-mix(in srgb, var(--c) 40%, transparent));
}
/* the inner glow: two crossed planes */
.crystal b {
position: absolute;
top: calc(var(--h) * -1);
left: calc(var(--w) * -0.8);
width: calc(var(--w) * 1.6);
height: var(--h);
transform-style: preserve-3d;
}
.crystal b::before,
.crystal b::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(50% 60% at 50% 72%, color-mix(in srgb, #fff 60%, var(--c)), color-mix(in srgb, var(--c) 45%, transparent) 40%, transparent);
animation: glow 3.6s ease-in-out var(--d) infinite alternate;
}
.crystal b::after {
transform: rotateY(90deg);
}
/* the rock: an uneven slab laid flat */
.rock {
position: absolute;
top: -24px;
left: -68px;
width: 136px;
height: 136px;
clip-path: polygon(22% 4%, 62% 0, 92% 18%, 100% 55%, 84% 90%, 46% 100%, 12% 86%, 0 48%);
background: radial-gradient(circle, #ae98ff 0 6%, #4a3e8d 24%, #2e2a5d 60%, #3c3576);
transform: translateY(1px) rotateX(90deg);
}
@keyframes spin {
from { transform: rotateX(-22deg) rotateY(0deg); }
to { transform: rotateX(-22deg) rotateY(360deg); }
}
@keyframes glow {
from { opacity: 0.35; }
to { opacity: 1; }
}
$floor: 44px; // the rock's surface, below the centre so the cluster turns round its middle
$tip: 40deg; // lean of a tip facet from upright
$spin: 30s;
$edge: color-mix(in srgb, var(--c) 85%, #fff);
// Five hexagonal prisms growing out of one rock. Every crystal is set up by the same numbers
// (--w width of a side, --h height, --az / --tilt / --off where and how it leans) and built the
// same way: 6 side panels, each carrying its own tip facet as a ::before.
.d-crystal {
position: relative;
width: 0;
height: 0;
transform-style: preserve-3d;
animation: d-crystal-spin $spin linear infinite;
// one crystal: stand on the floor, face its direction, step out from the centre, lean outward
&__c {
position: absolute;
transform-style: preserve-3d;
transform: translateY($floor) rotateY(var(--az)) translateZ(var(--off)) rotateX(calc(var(--tilt) * -1));
// side panels: a closed hexagonal ring. Apothem = side × √3 / 2.
i {
position: absolute;
top: calc(var(--h) * -1);
left: calc(var(--w) / -2);
width: var(--w);
height: var(--h);
transform-style: preserve-3d; // so the tip on top can fold in 3D
transform: rotateY(calc(var(--i) * 60deg)) translateZ(calc(var(--w) * 0.866));
background:
linear-gradient(90deg, transparent 30%, rgb(255 255 255 / 0.2) 42%, transparent 54%),
linear-gradient(
to top,
color-mix(in srgb, var(--c) 62%, transparent),
color-mix(in srgb, var(--c) 14%, transparent) 70%,
color-mix(in srgb, var(--c) 28%, transparent)
);
box-shadow:
inset 1px 0 color-mix(in srgb, var(--c) 80%, transparent),
inset -1px 0 color-mix(in srgb, var(--c) 80%, transparent),
inset 0 1px $edge;
// the tip facet: a triangle hinged on the panel's top edge, leaned in by 40deg.
// Its slant height is apothem / sin(40deg) = 1.347 × side, so all six tips meet on the axis.
&::before {
content: '';
position: absolute;
bottom: 100%;
left: 0;
width: 100%;
height: calc(var(--w) * 1.347);
transform-origin: 50% 100%;
transform: rotateX($tip);
clip-path: polygon(50% 0, 0 100%, 100% 100%);
background:
linear-gradient(to top left, transparent calc(50% - 1px), $edge calc(50% - 1px), $edge 50%, transparent 50%) left /
50% 100% no-repeat,
linear-gradient(to top right, transparent calc(50% - 1px), $edge calc(50% - 1px), $edge 50%, transparent 50%) right /
50% 100% no-repeat,
linear-gradient(color-mix(in srgb, var(--c) 20%, #fff 30%), color-mix(in srgb, var(--c) 40%, transparent));
}
&:nth-child(even) {
--c: var(--c2);
}
}
// the inner glow: two crossed planes of soft light up the middle, breathing on their own beat
b {
position: absolute;
top: calc(var(--h) * -1);
left: calc(var(--w) * -0.8);
width: calc(var(--w) * 1.6);
height: var(--h);
transform-style: preserve-3d;
&::before,
&::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(
50% 60% at 50% 72%,
color-mix(in srgb, #fff 60%, var(--c)),
color-mix(in srgb, var(--c) 45%, transparent) 40%,
transparent 100%
);
animation: d-crystal-glow 3.6s ease-in-out var(--d) infinite alternate;
}
&::after {
transform: rotateY(90deg);
}
}
}
// the rock: an uneven slab laid flat, lit from the crystals' roots
&__rock {
position: absolute;
top: $floor - 68px;
left: -68px;
width: 136px;
height: 136px;
clip-path: polygon(22% 4%, 62% 0, 92% 18%, 100% 55%, 84% 90%, 46% 100%, 12% 86%, 0 48%);
background: radial-gradient(
circle,
color-mix(in srgb, var(--accent) 70%, #fff) 0 6%,
color-mix(in srgb, var(--accent) 45%, var(--surface-solid)) 24%,
color-mix(in srgb, var(--accent) 22%, var(--surface-solid)) 60%,
color-mix(in srgb, var(--accent) 34%, var(--surface-solid))
);
transform: translateY(1px) rotateX(90deg);
}
}
@keyframes d-crystal-spin {
from {
transform: rotateX(-22deg) rotateY(0deg);
}
to {
transform: rotateX(-22deg) rotateY(360deg);
}
}
@keyframes d-crystal-glow {
from {
opacity: 0.35;
}
to {
opacity: 1;
}
}