Rotating cube
Pure CSSSix faces placed with rotate + translateZ, spun by a single keyframe animation.
JS places the dots on a Fibonacci sphere once; the spin itself is a plain CSS animation.
Your edited version
rotateY(longitude) rotateX(latitude) translateZ(radius): aim, then push outward. Same idea as the carousel, in two axes.DOM generated from a formularotateY · rotateX · translateZ per dotCSS keyframe spin<div class="scene">
<div class="ball"></div>
</div>
.scene {
perspective: 600px;
}
.ball {
--r: 130px;
position: relative;
width: 0;
height: 0;
transform-style: preserve-3d;
animation: ball-spin 16s linear infinite;
}
.ball i {
position: absolute;
top: -4px;
left: -4px;
width: 8px;
height: 8px;
border-radius: 50%;
background: radial-gradient(circle, #fff 15%, #ffb547 60%);
}
@keyframes ball-spin {
from { transform: rotateX(-18deg) rotateY(0deg); }
to { transform: rotateX(-18deg) rotateY(360deg); }
}
const ball = document.querySelector('.ball');
const COUNT = 120;
const GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5));
for (let i = 0; i < COUNT; i++) {
const lat = Math.asin(1 - (i / (COUNT - 1)) * 2); // -90° … 90°
const lon = i * GOLDEN_ANGLE;
const dot = document.createElement('i');
dot.style.transform =
'rotateY(' + lon + 'rad) rotateX(' + lat + 'rad) translateZ(var(--r))';
ball.append(dot);
}
.d-sphere {
display: grid;
grid-template-rows: 1fr auto;
width: 100%;
height: 100%;
padding: 8px 14px 10px;
&__view {
display: grid;
place-items: center;
perspective: 600px;
}
&__ball {
--r: 80px;
position: relative;
width: 0;
height: 0;
transform-style: preserve-3d;
animation: d-sphere-spin 16s linear infinite;
// Each <i> gets its own rotateY · rotateX · translateZ(var(--r)) inline from JS.
i {
position: absolute;
top: -3px;
left: -3px;
width: 6px;
height: 6px;
border-radius: 50%;
background: radial-gradient(circle, #fff 15%, var(--warm) 60%);
}
}
label {
display: flex;
align-items: center;
gap: 8px;
color: var(--muted);
font-family: var(--mono);
font-size: 11px;
}
output {
min-width: 3ch;
color: var(--text);
}
input {
flex: 1;
accent-color: var(--warm);
}
}
@keyframes d-sphere-spin {
from {
transform: rotateX(-18deg) rotateY(0deg);
}
to {
transform: rotateX(-18deg) rotateY(360deg);
}
}