3D carousel

3D 캐러셀

Cards placed evenly around a cylinder, with the whole group rotating — a carousel where cards continuously orbit from front to back. Unlike coverflow, nothing "switches index" — the ring itself just keeps turning.

Also known as: Ring carouselCylinder carousel
···
html
<div class="c3wrap"><div class="ring" id="ring"></div></div>
css
.c3wrap{perspective:600px;width:80%;height:62%;display:grid;place-items:center}
.ring{position:relative;width:1px;height:1px;transform-style:preserve-3d}
.card3{position:absolute;top:50%;left:50%;width:clamp(48px,17vmin,74px);height:clamp(64px,22vmin,96px);
  margin:calc(clamp(64px,22vmin,96px) / -2) 0 0 calc(clamp(48px,17vmin,74px) / -2);
  border-radius:8px;display:grid;place-items:center;font:800 16px/1 sans-serif;color:#fff;
  background:linear-gradient(160deg, var(--accent), var(--accent-2));backface-visibility:hidden}
js
const ring = document.getElementById('ring');
const N = 7;
const radius = 92;
const cards = [];
for (let i = 0; i < N; i++) {
  const c = document.createElement('div');
  c.className = 'card3';
  c.textContent = String(i + 1);
  const angle = (360 / N) * i;
  c.dataset.angle = String(angle);
  c.style.transform = 'rotateY(' + angle + 'deg) translateZ(' + radius + 'px)';
  ring.appendChild(c);
  cards.push(c);
}
let theta = 0;
function loop() {
  theta = (theta + 0.35) % 360;
  ring.style.transform = 'rotateY(' + theta + 'deg)';
  cards.forEach((c) => {
    const a = ((parseFloat(c.dataset.angle) + theta) % 360 + 360) % 360;
    const front = a > 180 ? 360 - a : a;
    c.style.opacity = String(0.35 + (1 - front / 180) * 0.65);
  });
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);

Card i's position is set with rotateY(i × 360° / N) translateZ(radius) — spreading N cards evenly around a cylinder's circumference. Give the parent group (the "ring") transform-style: preserve-3d, and keep rotating the whole group by rotateY(θ); every card turns with the cylinder's surface, since each only needs to hold its own fixed angle while a single θ update spins the entire set.

To make the forward-facing card read clearly, normalize each card's current angle (its own angle + θ) to 0–360° and fade opacity as it approaches 180° (the back) — that sells the depth much more convincingly. If cards hold text, set backface-visibility: hidden on the back-facing ones so mirrored text doesn't show through.

Where coverflow shows one item large and centered with the rest as context, a 3D carousel keeps everything continuously turning and glimpsed in passing — it's less about reading any one item closely and more about conveying the presence and mood of a whole set.

When to use

Use it for logo walls or product showcases where the impression of "there are many" is the point itself. If users need to pick and examine one item closely, coverflow or a plain carousel works better.