3D Carousel Ring
Eight panels arranged in a circle in 3D space, rotating like a carousel. The radius is calculated with trigonometry so the panels meet edge to edge.
The code
Plain HTML and CSS with no dependencies. Copy a single file, or choose "Full file" for a complete page you can save as index.html and open in a browser.
<div class="stage">
<div class="ring">
<div class="panel" style="--i: 0">React</div>
<div class="panel" style="--i: 1">Next.js</div>
<div class="panel" style="--i: 2">Node.js</div>
<div class="panel" style="--i: 3">MongoDB</div>
<div class="panel" style="--i: 4">Python</div>
<div class="panel" style="--i: 5">AWS</div>
<div class="panel" style="--i: 6">Docker</div>
<div class="panel" style="--i: 7">AI</div>
</div>
</div>The AI prompt
Paste this into an AI coding tool to generate the same 3d scene, then ask it to adapt the colours, text or framework to your project.
Create a rotating 3D carousel ring using only HTML and CSS (no JavaScript). Requirements: - A stage, 170px wide and 220px tall, with perspective: 1100px. - A "ring" element with transform-style: preserve-3d that contains eight panels (labels: React, Next.js, Node.js, MongoDB, Python, AWS, Docker, AI). Give each panel an inline CSS variable --i from 0 to 7. - Each panel is absolutely positioned to fill the stage and transformed with rotateY(calc(var(--i) * 360deg / 8)) translateZ(235px), so the eight panels form a circle. (235px is roughly (170 / 2) / tan(22.5deg) plus a small gap.) - Panels have an 18px radius, a translucent white border, white bold text and alternate between a solid indigo gradient and a solid orange gradient. Add backface-visibility: hidden (with the -webkit- prefix) so panels facing away from the viewer are hidden and their mirrored text never shows through. - Animate the ring with keyframes from "translateZ(-235px) rotateY(0deg)" to "translateZ(-235px) rotateY(-360deg)" over 24 seconds, linear, infinite. The negative translateZ moves the ring back so the front panel sits at the screen plane. Pause on hover. - Respect prefers-reduced-motion by showing a static angle. - Centre it on a dark background. Return one HTML file with a <style> block.
How to build it, step by step
- 1
Give every panel an index with an inline CSS variable (--i). One CSS rule can then position all of them.
- 2
Rotate each panel around the Y axis by its share of the circle: index x (360 / number of panels).
- 3
After rotating, translateZ pushes the panel outward along the direction it now faces, placing it on the circumference.
- 4
Work out the radius with trigonometry: radius = (panel width / 2) / tan(180 / count). For 8 panels of 170px that is about 205px; add a little for gaps.
- 5
Move the whole ring back by the same radius with translateZ(-radius) so the nearest panel is at normal size instead of zoomed in.
- 6
Rotate the ring, not the panels, to spin the carousel.
- 7
Add backface-visibility: hidden to the panels. Panels on the far side face away from you, so this hides them and keeps the front of the ring clean.
Customisation tips
- Change the panel count by updating --count, the --i values and the radius formula.
- Replace the labels with images for a 3D photo gallery.
- Add Previous and Next buttons that change a --step variable and use rotateY(calc(var(--step) * -45deg)) with a transition instead of the animation.