36 CSS Stacked Cards13 / 36
Staircase Bricks
Cards staggered by fixed, repeating horizontal and vertical offsets into a strict stair-step cascade, so a uniform edge of every card stays visible. Hover any step to slide it out and read its full face.
Published Updated
The code
<section class="scd-13" aria-label="Staircase cascade of cards">
<div class="scd-13__stair">
<a class="scd-13__card" href="#" style="--i:0;--c:oklch(0.64 0.16 265)"><b>Plan</b><span>Scope & milestones</span></a>
<a class="scd-13__card" href="#" style="--i:1;--c:oklch(0.64 0.15 210)"><b>Design</b><span>Flows & system</span></a>
<a class="scd-13__card" href="#" style="--i:2;--c:oklch(0.66 0.15 160)"><b>Build</b><span>Ship in slices</span></a>
<a class="scd-13__card" href="#" style="--i:3;--c:oklch(0.68 0.16 90)"><b>Launch</b><span>Measure & iterate</span></a>
</div>
</section><section class="scd-13" aria-label="Staircase cascade of cards">
<div class="scd-13__stair">
<a class="scd-13__card" href="#" style="--i:0;--c:oklch(0.64 0.16 265)"><b>Plan</b><span>Scope & milestones</span></a>
<a class="scd-13__card" href="#" style="--i:1;--c:oklch(0.64 0.15 210)"><b>Design</b><span>Flows & system</span></a>
<a class="scd-13__card" href="#" style="--i:2;--c:oklch(0.66 0.15 160)"><b>Build</b><span>Ship in slices</span></a>
<a class="scd-13__card" href="#" style="--i:3;--c:oklch(0.68 0.16 90)"><b>Launch</b><span>Measure & iterate</span></a>
</div>
</section>.scd-13,
.scd-13 *,
.scd-13 *::before,
.scd-13 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-13 {
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: #12141c;
}
.scd-13__stair {
position: relative;
width: 260px;
height: 280px;
}
.scd-13__card {
position: absolute;
left: 0;
top: 0;
width: 190px;
height: 120px;
padding: 20px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 18px 34px -20px rgba(0,0,0,.8);
transform: translate(calc(var(--i) * 24px),calc(var(--i) * 46px));
z-index: calc(var(--i) + 1);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
display: flex;
flex-direction: column;
gap: 6px;
}
.scd-13__card b {
font-size: 19px;
font-weight: 800;
}
.scd-13__card span {
font-size: 13px;
opacity: .9;
}
.scd-13__card:hover,
.scd-13__card:focus-visible {
transform: translate(calc(var(--i) * 24px + 40px),calc(var(--i) * 46px - 8px));
box-shadow: 0 28px 48px -20px rgba(0,0,0,.9);
z-index: 20;
outline: none;
}
.scd-13__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 28px 48px -20px rgba(0,0,0,.9);
}
@media (prefers-reduced-motion: reduce) {
.scd-13__card {
transition: box-shadow .2s;
}
}.scd-13,
.scd-13 *,
.scd-13 *::before,
.scd-13 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-13 {
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: #12141c;
}
.scd-13__stair {
position: relative;
width: 260px;
height: 280px;
}
.scd-13__card {
position: absolute;
left: 0;
top: 0;
width: 190px;
height: 120px;
padding: 20px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 18px 34px -20px rgba(0,0,0,.8);
transform: translate(calc(var(--i) * 24px),calc(var(--i) * 46px));
z-index: calc(var(--i) + 1);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
display: flex;
flex-direction: column;
gap: 6px;
}
.scd-13__card b {
font-size: 19px;
font-weight: 800;
}
.scd-13__card span {
font-size: 13px;
opacity: .9;
}
.scd-13__card:hover,
.scd-13__card:focus-visible {
transform: translate(calc(var(--i) * 24px + 40px),calc(var(--i) * 46px - 8px));
box-shadow: 0 28px 48px -20px rgba(0,0,0,.9);
z-index: 20;
outline: none;
}
.scd-13__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 28px 48px -20px rgba(0,0,0,.9);
}
@media (prefers-reduced-motion: reduce) {
.scd-13__card {
transition: box-shadow .2s;
}
}/* No JavaScript — an index-driven constant translate builds the staircase; :hover slides the target step out along the diagonal. */
/* No JavaScript — an index-driven constant translate builds the staircase; :hover slides the target step out along the diagonal. */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: Staircase Bricks
Source: https://codefronts.com/components/css-stacked-cards/staircase-bricks/
Cards staggered by fixed, repeating horizontal and vertical offsets into a strict stair-step cascade, so a uniform edge of every card stays visible. Hover any step to slide it out and read its full face.
## HTML
```html
<section class="scd-13" aria-label="Staircase cascade of cards">
<div class="scd-13__stair">
<a class="scd-13__card" href="#" style="--i:0;--c:oklch(0.64 0.16 265)"><b>Plan</b><span>Scope & milestones</span></a>
<a class="scd-13__card" href="#" style="--i:1;--c:oklch(0.64 0.15 210)"><b>Design</b><span>Flows & system</span></a>
<a class="scd-13__card" href="#" style="--i:2;--c:oklch(0.66 0.15 160)"><b>Build</b><span>Ship in slices</span></a>
<a class="scd-13__card" href="#" style="--i:3;--c:oklch(0.68 0.16 90)"><b>Launch</b><span>Measure & iterate</span></a>
</div>
</section>
```
## CSS
```css
.scd-13,
.scd-13 *,
.scd-13 *::before,
.scd-13 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-13 {
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: #12141c;
}
.scd-13__stair {
position: relative;
width: 260px;
height: 280px;
}
.scd-13__card {
position: absolute;
left: 0;
top: 0;
width: 190px;
height: 120px;
padding: 20px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 18px 34px -20px rgba(0,0,0,.8);
transform: translate(calc(var(--i) * 24px),calc(var(--i) * 46px));
z-index: calc(var(--i) + 1);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
display: flex;
flex-direction: column;
gap: 6px;
}
.scd-13__card b {
font-size: 19px;
font-weight: 800;
}
.scd-13__card span {
font-size: 13px;
opacity: .9;
}
.scd-13__card:hover,
.scd-13__card:focus-visible {
transform: translate(calc(var(--i) * 24px + 40px),calc(var(--i) * 46px - 8px));
box-shadow: 0 28px 48px -20px rgba(0,0,0,.9);
z-index: 20;
outline: none;
}
.scd-13__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 28px 48px -20px rgba(0,0,0,.9);
}
@media (prefers-reduced-motion: reduce) {
.scd-13__card {
transition: box-shadow .2s;
}
}
```
## JavaScript
```js
/* No JavaScript — an index-driven constant translate builds the staircase; :hover slides the target step out along the diagonal. */
```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: Staircase Bricks
Source: https://codefronts.com/components/css-stacked-cards/staircase-bricks/
Cards staggered by fixed, repeating horizontal and vertical offsets into a strict stair-step cascade, so a uniform edge of every card stays visible. Hover any step to slide it out and read its full face.
## HTML
```html
<section class="scd-13" aria-label="Staircase cascade of cards">
<div class="scd-13__stair">
<a class="scd-13__card" href="#" style="--i:0;--c:oklch(0.64 0.16 265)"><b>Plan</b><span>Scope & milestones</span></a>
<a class="scd-13__card" href="#" style="--i:1;--c:oklch(0.64 0.15 210)"><b>Design</b><span>Flows & system</span></a>
<a class="scd-13__card" href="#" style="--i:2;--c:oklch(0.66 0.15 160)"><b>Build</b><span>Ship in slices</span></a>
<a class="scd-13__card" href="#" style="--i:3;--c:oklch(0.68 0.16 90)"><b>Launch</b><span>Measure & iterate</span></a>
</div>
</section>
```
## CSS
```css
.scd-13,
.scd-13 *,
.scd-13 *::before,
.scd-13 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.scd-13 {
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: #12141c;
}
.scd-13__stair {
position: relative;
width: 260px;
height: 280px;
}
.scd-13__card {
position: absolute;
left: 0;
top: 0;
width: 190px;
height: 120px;
padding: 20px;
border-radius: 16px;
color: #fff;
text-decoration: none;
background: var(--c);
box-shadow: 0 18px 34px -20px rgba(0,0,0,.8);
transform: translate(calc(var(--i) * 24px),calc(var(--i) * 46px));
z-index: calc(var(--i) + 1);
transition: transform .35s cubic-bezier(.3,.9,.3,1),box-shadow .3s;
display: flex;
flex-direction: column;
gap: 6px;
}
.scd-13__card b {
font-size: 19px;
font-weight: 800;
}
.scd-13__card span {
font-size: 13px;
opacity: .9;
}
.scd-13__card:hover,
.scd-13__card:focus-visible {
transform: translate(calc(var(--i) * 24px + 40px),calc(var(--i) * 46px - 8px));
box-shadow: 0 28px 48px -20px rgba(0,0,0,.9);
z-index: 20;
outline: none;
}
.scd-13__card:focus-visible {
box-shadow: 0 0 0 3px #fff,0 28px 48px -20px rgba(0,0,0,.9);
}
@media (prefers-reduced-motion: reduce) {
.scd-13__card {
transition: box-shadow .2s;
}
}
```
## JavaScript
```js
/* No JavaScript — an index-driven constant translate builds the staircase; :hover slides the target step out along the diagonal. */
```How this works
Each card is offset from the previous by a constant translate derived from its index (--i), producing an even staircase where one corner of every card peeks. Card z-index tracks the index so upper steps overlap lower ones cleanly. On :hover/:focus-visible the target card shifts out along the diagonal and lifts, exposing its content without disturbing the cascade.
Cards are focusable links; the stair is built from a single index-driven rule, so lengthening it is just adding one more item.
Make it yours
- Change the step size via the
--ioffset multipliers. - Reverse direction by negating the offsets.
- Adjust which corner peeks by shifting the base translate.
- Recolour steps for a gradient staircase.
Gotchas — read before shipping
- Keep
z-indexin step with the index so overlaps read correctly. - Leave a consistent peek so every card's edge stays clickable.
- Give the container room for the full diagonal span.
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+.
Index-driven transforms; supported in all modern browsers. No JS.