Cards stacked with subtle rotation. The top card is active; the rest peek out behind. Luxury feel for hand-picked collections.
Each card is absolutely positioned over the others. The "active" card has transform: translateY(0) rotate(0), the others get progressively higher Y offsets and small rotations to look like they're stacked behind. Radio inputs hold which card is on top; :has() on the parent watches the radios and re-applies the transform classes to whichever cards should be in each position.
<div class="stack">
<input type="radio" name="s" id="s1" checked>
<input type="radio" name="s" id="s2">
...
<div class="card c1">...</div>
<div class="card c2">...</div>
</div>
<div class="stack-nav">
<label for="s1">1</label>
<label for="s2">2</label>
</div>
.stack .card { position: absolute; inset: 0; transition: transform 0.5s; }
.stack .c1 { transform: translateY(0); z-index: 4; }
.stack .c2 { transform: translateY(12px) rotate(2deg); z-index: 3; opacity: 0.92; }
.stack:has(#s2:checked) .c2 { transform: translateY(0); z-index: 4; opacity: 1; }
.stack:has(#s2:checked) .c1 { transform: translateY(36px) rotate(3deg); z-index: 1; opacity: 0.7; }
Add swipe gestures — for a true "Tinder card" feel, you'd need ~30 lines of JS to handle pointer events. Pure-CSS click-only is honest and works everywhere.
Fan instead of stack — change translateY to translateX with bigger rotations (e.g. 8°, -8°). Each card peeks from a different angle like cards in a hand. Strong "curated selection" feel.
Auto-cycle — pair with a CSS @keyframes animation on the input checked state if you want it to advance automatically. Use cautiously — auto-motion can be disorienting on phones.
Compatibility: :has() needs Safari 15.4+, Chrome 105+, Firefox 121+.