36 CSS Stacked Cards15 / 36
Cascade Lift
A vertical stack of cards gently resting on one another. Hover any card and it slides upward while sibling selectors push the cards below it down and out of the way — a clean, physical way to preview one item without leaving the stack.
Published Updated
The code
<section class="scd-15" aria-label="Cascade-lift card stack">
<div class="scd-15__stack">
<a class="scd-15__card" href="#" style="--c:oklch(0.64 0.16 20)"><b>Espresso</b><span>Single origin · 30ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.62 0.14 50)"><b>Cortado</b><span>Equal parts · 90ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.6 0.12 80)"><b>Flat white</b><span>Micro-foam · 160ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.58 0.1 110)"><b>Cold brew</b><span>18h steep · 240ml</span></a>
</div>
</section><section class="scd-15" aria-label="Cascade-lift card stack">
<div class="scd-15__stack">
<a class="scd-15__card" href="#" style="--c:oklch(0.64 0.16 20)"><b>Espresso</b><span>Single origin · 30ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.62 0.14 50)"><b>Cortado</b><span>Equal parts · 90ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.6 0.12 80)"><b>Flat white</b><span>Micro-foam · 160ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.58 0.1 110)"><b>Cold brew</b><span>18h steep · 240ml</span></a>
</div>
</section>.scd-15,
.scd-15 *,
.scd-15 *::before,
.scd-15 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-15 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
background: #161310;
}
.scd-15__stack {
width: min(320px,100%);
}
.scd-15__card {
display: flex;
flex-direction: column;
gap: 5px;
padding: 20px 24px;
margin-top: -16px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 14px 30px -18px rgba(0,0,0,.8);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
}
.scd-15__card:first-child {
margin-top: 0;
}
.scd-15__card b {
font-size: 18px;
font-weight: 800;
}
.scd-15__card span {
font-size: 13px;
opacity: .9;
}
.scd-15__card:hover,
.scd-15__card:focus-visible {
transform: translateY(-18px) scale(1.03);
box-shadow: 0 26px 44px -20px rgba(0,0,0,.9);
z-index: 5;
outline: none;
}
.scd-15__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 26px 44px -20px rgba(0,0,0,.9);
}
.scd-15__card:hover ~ .scd-15__card,
.scd-15__card:focus-visible ~ .scd-15__card {
transform: translateY(30px);
}
@media (prefers-reduced-motion: reduce) {
.scd-15__card {
transition: box-shadow .2s;
}
}.scd-15,
.scd-15 *,
.scd-15 *::before,
.scd-15 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-15 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
background: #161310;
}
.scd-15__stack {
width: min(320px,100%);
}
.scd-15__card {
display: flex;
flex-direction: column;
gap: 5px;
padding: 20px 24px;
margin-top: -16px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 14px 30px -18px rgba(0,0,0,.8);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
}
.scd-15__card:first-child {
margin-top: 0;
}
.scd-15__card b {
font-size: 18px;
font-weight: 800;
}
.scd-15__card span {
font-size: 13px;
opacity: .9;
}
.scd-15__card:hover,
.scd-15__card:focus-visible {
transform: translateY(-18px) scale(1.03);
box-shadow: 0 26px 44px -20px rgba(0,0,0,.9);
z-index: 5;
outline: none;
}
.scd-15__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 26px 44px -20px rgba(0,0,0,.9);
}
.scd-15__card:hover ~ .scd-15__card,
.scd-15__card:focus-visible ~ .scd-15__card {
transform: translateY(30px);
}
@media (prefers-reduced-motion: reduce) {
.scd-15__card {
transition: box-shadow .2s;
}
}/* No JavaScript — the general-sibling combinator (:hover ~ .card) pushes every card below the hovered one down while it lifts up. */
/* No JavaScript — the general-sibling combinator (:hover ~ .card) pushes every card below the hovered one down while it lifts up. */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: Cascade Lift
Source: https://codefronts.com/components/css-stacked-cards/cascade-lift/
A vertical stack of cards gently resting on one another. Hover any card and it slides upward while sibling selectors push the cards below it down and out of the way — a clean, physical way to preview one item without leaving the stack.
## HTML
```html
<section class="scd-15" aria-label="Cascade-lift card stack">
<div class="scd-15__stack">
<a class="scd-15__card" href="#" style="--c:oklch(0.64 0.16 20)"><b>Espresso</b><span>Single origin · 30ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.62 0.14 50)"><b>Cortado</b><span>Equal parts · 90ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.6 0.12 80)"><b>Flat white</b><span>Micro-foam · 160ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.58 0.1 110)"><b>Cold brew</b><span>18h steep · 240ml</span></a>
</div>
</section>
```
## CSS
```css
.scd-15,
.scd-15 *,
.scd-15 *::before,
.scd-15 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-15 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
background: #161310;
}
.scd-15__stack {
width: min(320px,100%);
}
.scd-15__card {
display: flex;
flex-direction: column;
gap: 5px;
padding: 20px 24px;
margin-top: -16px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 14px 30px -18px rgba(0,0,0,.8);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
}
.scd-15__card:first-child {
margin-top: 0;
}
.scd-15__card b {
font-size: 18px;
font-weight: 800;
}
.scd-15__card span {
font-size: 13px;
opacity: .9;
}
.scd-15__card:hover,
.scd-15__card:focus-visible {
transform: translateY(-18px) scale(1.03);
box-shadow: 0 26px 44px -20px rgba(0,0,0,.9);
z-index: 5;
outline: none;
}
.scd-15__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 26px 44px -20px rgba(0,0,0,.9);
}
.scd-15__card:hover ~ .scd-15__card,
.scd-15__card:focus-visible ~ .scd-15__card {
transform: translateY(30px);
}
@media (prefers-reduced-motion: reduce) {
.scd-15__card {
transition: box-shadow .2s;
}
}
```
## JavaScript
```js
/* No JavaScript — the general-sibling combinator (:hover ~ .card) pushes every card below the hovered one down while it lifts up. */
```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: Cascade Lift
Source: https://codefronts.com/components/css-stacked-cards/cascade-lift/
A vertical stack of cards gently resting on one another. Hover any card and it slides upward while sibling selectors push the cards below it down and out of the way — a clean, physical way to preview one item without leaving the stack.
## HTML
```html
<section class="scd-15" aria-label="Cascade-lift card stack">
<div class="scd-15__stack">
<a class="scd-15__card" href="#" style="--c:oklch(0.64 0.16 20)"><b>Espresso</b><span>Single origin · 30ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.62 0.14 50)"><b>Cortado</b><span>Equal parts · 90ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.6 0.12 80)"><b>Flat white</b><span>Micro-foam · 160ml</span></a>
<a class="scd-15__card" href="#" style="--c:oklch(0.58 0.1 110)"><b>Cold brew</b><span>18h steep · 240ml</span></a>
</div>
</section>
```
## CSS
```css
.scd-15,
.scd-15 *,
.scd-15 *::before,
.scd-15 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-15 {
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
background: #161310;
}
.scd-15__stack {
width: min(320px,100%);
}
.scd-15__card {
display: flex;
flex-direction: column;
gap: 5px;
padding: 20px 24px;
margin-top: -16px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 14px 30px -18px rgba(0,0,0,.8);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
}
.scd-15__card:first-child {
margin-top: 0;
}
.scd-15__card b {
font-size: 18px;
font-weight: 800;
}
.scd-15__card span {
font-size: 13px;
opacity: .9;
}
.scd-15__card:hover,
.scd-15__card:focus-visible {
transform: translateY(-18px) scale(1.03);
box-shadow: 0 26px 44px -20px rgba(0,0,0,.9);
z-index: 5;
outline: none;
}
.scd-15__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 26px 44px -20px rgba(0,0,0,.9);
}
.scd-15__card:hover ~ .scd-15__card,
.scd-15__card:focus-visible ~ .scd-15__card {
transform: translateY(30px);
}
@media (prefers-reduced-motion: reduce) {
.scd-15__card {
transition: box-shadow .2s;
}
}
```
## JavaScript
```js
/* No JavaScript — the general-sibling combinator (:hover ~ .card) pushes every card below the hovered one down while it lifts up. */
```How this works
Cards sit in a column overlapping via negative margin-top. The trick is the general-sibling combinator: .card:hover ~ .card targets every card after the hovered one and translates it down, while the hovered card itself lifts up. The result is a parting-of-the-waters reveal centred on your pointer — all pure CSS, no indices to manage.
Cards are focusable, so :focus plus the same sibling rule gives keyboard users the identical lift. Reduced-motion shortens the slide.
Make it yours
- Change overlap via the resting negative
margin-top. - Set how far lower cards move with the sibling
translateY. - Add a scale/shadow bump on the lifted card.
- Recolour cards per item.
Gotchas — read before shipping
- Use
~(general sibling), not+, so all following cards move. - Add
:focus-within/:focusrules for keyboard parity. - Keep enough peek so every card is hoverable.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 113+ | 111+ |
Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome 49+.
General-sibling combinator + transforms; universal. No JS.