36 CSS Stacked Cards36 / 36
Spiral Tower
Cards arranged in a continuously rotating 3D helix around a central axis; hover pauses the spin. Hypnotic and bold. Perfect for hero showcases, featured collections, or attention-grabbing displays.
Published Updated
The code
<div class="scd-36">
<div class="scd-36__stage">
<div class="scd-36__spiral">
<div class="scd-36__card">01</div>
<div class="scd-36__card">02</div>
<div class="scd-36__card">03</div>
<div class="scd-36__card">04</div>
<div class="scd-36__card">05</div>
</div>
</div>
</div><div class="scd-36">
<div class="scd-36__stage">
<div class="scd-36__spiral">
<div class="scd-36__card">01</div>
<div class="scd-36__card">02</div>
<div class="scd-36__card">03</div>
<div class="scd-36__card">04</div>
<div class="scd-36__card">05</div>
</div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Major+Mono+Display&family=Jost:wght@400;500&display=swap');
.scd-36,
.scd-36 *,
.scd-36 *::before,
.scd-36 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-36 {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
background: radial-gradient(circle at 50% 50%,#1e0a2e,#080410);
font-family: 'Jost', sans-serif;
}
.scd-36__stage {
perspective: 1200px;
width: 240px;
height: 400px;
}
.scd-36__spiral {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
animation: scd-36-spin 14s linear infinite;
}
@keyframes scd-36-spin {
to {
transform: rotateY(360deg);
}
}
.scd-36__stage:hover .scd-36__spiral {
animation-play-state: paused;
}
.scd-36__card {
position: absolute;
left: 50%;
top: 50%;
width: 120px;
height: 160px;
margin: -80px -60px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-family: 'Major Mono Display', monospace;
font-size: 1.4rem;
box-shadow: 0 0 30px rgba(180,100,255,.25);
}
.scd-36__card:nth-child(1) {
transform: rotateY(0deg) translateZ(150px) translateY(-120px);
background: linear-gradient(150deg,#ee0979,#ff6a00);
}
.scd-36__card:nth-child(2) {
transform: rotateY(72deg) translateZ(150px) translateY(-60px);
background: linear-gradient(150deg,#7f00ff,#e100ff);
}
.scd-36__card:nth-child(3) {
transform: rotateY(144deg) translateZ(150px) translateY(0px);
background: linear-gradient(150deg,#00c6ff,#0072ff);
}
.scd-36__card:nth-child(4) {
transform: rotateY(216deg) translateZ(150px) translateY(60px);
background: linear-gradient(150deg,#11998e,#38ef7d);
}
.scd-36__card:nth-child(5) {
transform: rotateY(288deg) translateZ(150px) translateY(120px);
background: linear-gradient(150deg,#f7971e,#ffd200);
color: #623;
}
@media (prefers-reduced-motion: reduce) {
.scd-36__spiral {
animation: none !important;
transition: none !important;
}
}@import url('https://fonts.googleapis.com/css2?family=Major+Mono+Display&family=Jost:wght@400;500&display=swap');
.scd-36,
.scd-36 *,
.scd-36 *::before,
.scd-36 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-36 {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
background: radial-gradient(circle at 50% 50%,#1e0a2e,#080410);
font-family: 'Jost', sans-serif;
}
.scd-36__stage {
perspective: 1200px;
width: 240px;
height: 400px;
}
.scd-36__spiral {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
animation: scd-36-spin 14s linear infinite;
}
@keyframes scd-36-spin {
to {
transform: rotateY(360deg);
}
}
.scd-36__stage:hover .scd-36__spiral {
animation-play-state: paused;
}
.scd-36__card {
position: absolute;
left: 50%;
top: 50%;
width: 120px;
height: 160px;
margin: -80px -60px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-family: 'Major Mono Display', monospace;
font-size: 1.4rem;
box-shadow: 0 0 30px rgba(180,100,255,.25);
}
.scd-36__card:nth-child(1) {
transform: rotateY(0deg) translateZ(150px) translateY(-120px);
background: linear-gradient(150deg,#ee0979,#ff6a00);
}
.scd-36__card:nth-child(2) {
transform: rotateY(72deg) translateZ(150px) translateY(-60px);
background: linear-gradient(150deg,#7f00ff,#e100ff);
}
.scd-36__card:nth-child(3) {
transform: rotateY(144deg) translateZ(150px) translateY(0px);
background: linear-gradient(150deg,#00c6ff,#0072ff);
}
.scd-36__card:nth-child(4) {
transform: rotateY(216deg) translateZ(150px) translateY(60px);
background: linear-gradient(150deg,#11998e,#38ef7d);
}
.scd-36__card:nth-child(5) {
transform: rotateY(288deg) translateZ(150px) translateY(120px);
background: linear-gradient(150deg,#f7971e,#ffd200);
color: #623;
}
@media (prefers-reduced-motion: reduce) {
.scd-36__spiral {
animation: none !important;
transition: none !important;
}
}Here's a working CSS Stacked Card from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Spiral Tower
Source: https://codefronts.com/components/css-stacked-cards/spiral-tower/
Cards arranged in a continuously rotating 3D helix around a central axis; hover pauses the spin. Hypnotic and bold. Perfect for hero showcases, featured collections, or attention-grabbing displays.
## HTML
```html
<div class="scd-36">
<div class="scd-36__stage">
<div class="scd-36__spiral">
<div class="scd-36__card">01</div>
<div class="scd-36__card">02</div>
<div class="scd-36__card">03</div>
<div class="scd-36__card">04</div>
<div class="scd-36__card">05</div>
</div>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Major+Mono+Display&family=Jost:wght@400;500&display=swap');
.scd-36,
.scd-36 *,
.scd-36 *::before,
.scd-36 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-36 {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
background: radial-gradient(circle at 50% 50%,#1e0a2e,#080410);
font-family: 'Jost', sans-serif;
}
.scd-36__stage {
perspective: 1200px;
width: 240px;
height: 400px;
}
.scd-36__spiral {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
animation: scd-36-spin 14s linear infinite;
}
@keyframes scd-36-spin {
to {
transform: rotateY(360deg);
}
}
.scd-36__stage:hover .scd-36__spiral {
animation-play-state: paused;
}
.scd-36__card {
position: absolute;
left: 50%;
top: 50%;
width: 120px;
height: 160px;
margin: -80px -60px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-family: 'Major Mono Display', monospace;
font-size: 1.4rem;
box-shadow: 0 0 30px rgba(180,100,255,.25);
}
.scd-36__card:nth-child(1) {
transform: rotateY(0deg) translateZ(150px) translateY(-120px);
background: linear-gradient(150deg,#ee0979,#ff6a00);
}
.scd-36__card:nth-child(2) {
transform: rotateY(72deg) translateZ(150px) translateY(-60px);
background: linear-gradient(150deg,#7f00ff,#e100ff);
}
.scd-36__card:nth-child(3) {
transform: rotateY(144deg) translateZ(150px) translateY(0px);
background: linear-gradient(150deg,#00c6ff,#0072ff);
}
.scd-36__card:nth-child(4) {
transform: rotateY(216deg) translateZ(150px) translateY(60px);
background: linear-gradient(150deg,#11998e,#38ef7d);
}
.scd-36__card:nth-child(5) {
transform: rotateY(288deg) translateZ(150px) translateY(120px);
background: linear-gradient(150deg,#f7971e,#ffd200);
color: #623;
}
@media (prefers-reduced-motion: reduce) {
.scd-36__spiral {
animation: none !important;
transition: none !important;
}
}
```Here's a working CSS Stacked Card from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Spiral Tower
Source: https://codefronts.com/components/css-stacked-cards/spiral-tower/
Cards arranged in a continuously rotating 3D helix around a central axis; hover pauses the spin. Hypnotic and bold. Perfect for hero showcases, featured collections, or attention-grabbing displays.
## HTML
```html
<div class="scd-36">
<div class="scd-36__stage">
<div class="scd-36__spiral">
<div class="scd-36__card">01</div>
<div class="scd-36__card">02</div>
<div class="scd-36__card">03</div>
<div class="scd-36__card">04</div>
<div class="scd-36__card">05</div>
</div>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Major+Mono+Display&family=Jost:wght@400;500&display=swap');
.scd-36,
.scd-36 *,
.scd-36 *::before,
.scd-36 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-36 {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
background: radial-gradient(circle at 50% 50%,#1e0a2e,#080410);
font-family: 'Jost', sans-serif;
}
.scd-36__stage {
perspective: 1200px;
width: 240px;
height: 400px;
}
.scd-36__spiral {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
animation: scd-36-spin 14s linear infinite;
}
@keyframes scd-36-spin {
to {
transform: rotateY(360deg);
}
}
.scd-36__stage:hover .scd-36__spiral {
animation-play-state: paused;
}
.scd-36__card {
position: absolute;
left: 50%;
top: 50%;
width: 120px;
height: 160px;
margin: -80px -60px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-family: 'Major Mono Display', monospace;
font-size: 1.4rem;
box-shadow: 0 0 30px rgba(180,100,255,.25);
}
.scd-36__card:nth-child(1) {
transform: rotateY(0deg) translateZ(150px) translateY(-120px);
background: linear-gradient(150deg,#ee0979,#ff6a00);
}
.scd-36__card:nth-child(2) {
transform: rotateY(72deg) translateZ(150px) translateY(-60px);
background: linear-gradient(150deg,#7f00ff,#e100ff);
}
.scd-36__card:nth-child(3) {
transform: rotateY(144deg) translateZ(150px) translateY(0px);
background: linear-gradient(150deg,#00c6ff,#0072ff);
}
.scd-36__card:nth-child(4) {
transform: rotateY(216deg) translateZ(150px) translateY(60px);
background: linear-gradient(150deg,#11998e,#38ef7d);
}
.scd-36__card:nth-child(5) {
transform: rotateY(288deg) translateZ(150px) translateY(120px);
background: linear-gradient(150deg,#f7971e,#ffd200);
color: #623;
}
@media (prefers-reduced-motion: reduce) {
.scd-36__spiral {
animation: none !important;
transition: none !important;
}
}
```How this works
Cards arranged around a central vertical axis using rotate3d(0, 1, 0, N*72deg) translateZ(200px) per card — the rotate3d spins each card around the Y-axis to a distinct angle, and the translateZ pushes each card outward from the axis on its own plane. The result is a helix / spiral tower of cards.
The parent has animation:scd-36-spin 20s linear infinite — a @keyframes that rotates the whole tower continuously around the Y-axis. Each card stays visible as it rotates through the viewport.
On hover, the animation pauses via animation-play-state:paused — users can hover to inspect the tower without the cards spinning past.
Make it yours
- Change the number of cards — adjust the
rotate3dmultiplier (360 / N degrees per card). - Adjust the tower radius via the
translateZdistance. - Tune spin speed via the animation duration — 15s for energetic, 30s for calm.
- Rebrand each card independently — the spiral pattern doesn't care about palette.
- For hero showcases, populate each card with a real product / feature / testimonial.
Gotchas — read before shipping
- Continuous rotation MUST respect
prefers-reduced-motion:reduce— freeze the animation entirely and show a static composed view. - The spinning tower makes reading in-card text impossible — reserve for decorative or accent contexts, not for primary content delivery.
- GPU-composited 3D rotation is smooth on desktop but can stutter on older mobile — test at 30fps target.
- Ensure each card is keyboard-focusable and can be paused via
:focus-withinpausing the animation. - For accessible content, mirror the spiral with a plain grid layout that appears when JavaScript is disabled or motion is reduced.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 36+ | 9+ | 16+ | 36+ |
CSS 3D transforms, keyframes, and animation-play-state are universally supported.
Techniques used in this demo
3D transforms (perspective + preserve-3d)radial-gradient()MDN ↗@keyframesMDN ↗place-items / place-contentMDN ↗