Rotating cube
Pure CSSSix faces placed with rotate + translateZ, spun by a single keyframe animation.
Triangles cut with clip-path, leaned inward by exactly the angle that makes the tips meet.
Your edited version
clip-path: polygon(50% 0, 0 100%, 100% 100%).rotateY(n × 90deg) translateZ(base / 2) puts it on one side of the base.rotateX with transform-origin: bottom leans it inward. The angle that makes all four tips meet is asin((base / 2) / slant) — 30° when base and slant height are equal.rotateX(90deg).clip-path: polygon()transform-origin: bottomlean angle = asin((base / 2) / slant)<div class="scene">
<div class="pyramid">
<i></i><i></i><i></i><i></i>
<b></b>
</div>
</div>
.scene {
perspective: 800px;
}
.pyramid {
--base: 140px;
position: relative;
width: var(--base);
height: var(--base); /* slant height = base → lean is exactly 30deg */
transform-style: preserve-3d;
animation: pyramid-spin 10s linear infinite;
}
.pyramid i {
position: absolute;
inset: 0;
clip-path: polygon(50% 0, 0 100%, 100% 100%);
transform-origin: bottom center;
}
.pyramid i:nth-child(1) {
background: linear-gradient(#ffb547, #b3651a);
transform: rotateY(0deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}
.pyramid i:nth-child(2) {
background: linear-gradient(#ffc257, #c27420);
transform: rotateY(90deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}
.pyramid i:nth-child(3) {
background: linear-gradient(#ffcf6b, #d18427);
transform: rotateY(180deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}
.pyramid i:nth-child(4) {
background: linear-gradient(#ffdb80, #df942f);
transform: rotateY(270deg) translateZ(calc(var(--base) / 2)) rotateX(30deg);
}
/* floor */
.pyramid b {
position: absolute;
inset: auto 0 0;
height: var(--base);
background: #5f3311;
transform: translateY(50%) rotateX(90deg);
}
@keyframes pyramid-spin {
from { transform: rotateX(-18deg) rotateY(0deg); }
to { transform: rotateX(-18deg) rotateY(360deg); }
}
@use 'sass:math';
$base: 110px;
$slant: 110px; // height of each triangular face
// Lean each face inward until its tip reaches the centre line.
$lean: math.asin(math.div($base * 0.5, $slant));
.d-pyramid {
position: relative;
width: $base;
height: $slant;
transform-style: preserve-3d;
animation: d-pyramid-spin 10s linear infinite;
i {
position: absolute;
inset: 0;
clip-path: polygon(50% 0, 0 100%, 100% 100%);
transform-origin: bottom center;
@for $i from 1 through 4 {
&:nth-child(#{$i}) {
background: linear-gradient(hsl(30 + $i * 8, 95%, 62%), hsl(20 + $i * 8, 85%, 30% + $i * 4%));
transform: rotateY(($i - 1) * 90deg) translateZ($base * 0.5) rotateX($lean);
}
}
}
// base
b {
position: absolute;
bottom: 0;
left: 0;
width: $base;
height: $base;
background: hsl(25, 70%, 22%);
transform: translateY(50%) rotateX(90deg);
}
}
@keyframes d-pyramid-spin {
from {
transform: translateY(8px) rotateX(-18deg) rotateY(0deg);
}
to {
transform: translateY(8px) rotateX(-18deg) rotateY(360deg);
}
}