36 CSS Stacked Cards32 / 36

Pure CSSMIT licensed

Minimalist Bento Grid Stacked Cards

A dark, dashboard-style bento grid where one tile embeds a stacked mini-card component to conserve space — channel breakdowns sit collapsed inside a single cell and fan open on hover, while neighboring tiles show stats, a sparkline, and glow accents. Built for analytics dashboards and content-dense grids where stacking saves container real estate.

Published Updated

Live Demo
Try it

The code

<div class="scd-32">
  <div class="scd-32__stage">
    <div class="scd-32__tile scd-32__tile--tall scd-32__tile--channels">
      <span class="scd-32__lbl">Channels</span>
      <div class="scd-32__substack">
        <div class="scd-32__mini scd-32__mini--m1"><span class="scd-32__lbl">Organic</span><b>62%</b></div>
        <div class="scd-32__mini scd-32__mini--m2"><span class="scd-32__lbl">Paid</span><b>24%</b></div>
        <div class="scd-32__mini scd-32__mini--m3"><span class="scd-32__lbl">Referral</span><b>14%</b></div>
      </div>
    </div>
    <div class="scd-32__tile scd-32__tile--wide"><div class="scd-32__glow" style="background:#34d399"></div><span class="scd-32__lbl">Revenue</span><div class="scd-32__val">$48.2k <small>+12%</small></div><div class="scd-32__spark"><span style="height:40%"></span><span style="height:55%"></span><span style="height:45%"></span><span style="height:70%"></span><span style="height:60%"></span><span style="height:85%"></span><span style="height:100%"></span></div></div>
    <div class="scd-32__tile"><span class="scd-32__lbl">Users</span><div class="scd-32__val">9.1k</div></div>
    <div class="scd-32__tile"><span class="scd-32__lbl">Churn</span><div class="scd-32__val" style="color:#fca5a5">1.8%</div></div>
    <div class="scd-32__tile"><div class="scd-32__glow" style="background:#818cf8"></div><span class="scd-32__lbl">NPS</span><div class="scd-32__val">72</div></div>
  </div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&display=swap');

.scd-32,
.scd-32 *,
.scd-32 *::before,
.scd-32 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.scd-32 {
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  background: #0e0f13;
  font-family: 'Geist', sans-serif;
  padding: 20px;
}

.scd-32__stage {
  display: grid;
  grid-template-columns: repeat(3, 118px);
  grid-template-rows: repeat(3, 118px);
  gap: 12px;
}

.scd-32__tile {
  background: #191b22;
  border: 1px solid #262934;
  border-radius: 18px;
  padding: 16px;
  position: relative;
  overflow: hidden;
  transition: border-color .3s;
}

.scd-32__tile:hover {
  border-color: #3a4050;
}

.scd-32__lbl {
  font-size: .68rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #6b7280;
}

.scd-32__val {
  font-size: 1.6rem;
  font-weight: 700;
  color: #f3f4f6;
  margin-top: 4px;
}

.scd-32__val small {
  font-size: .8rem;
  color: #34d399;
}

.scd-32__tile--wide {
  grid-column: span 2;
}

.scd-32__tile--tall {
  grid-row: span 2;
}

.scd-32__tile--channels {
  overflow: visible;
  z-index: 5;
}

.scd-32__tile--channels:hover {
  z-index: 20;
}

.scd-32__substack {
  position: absolute;
  bottom: 14px;
  left: 16px;
  right: 16px;
  height: 54px;
}

.scd-32__mini {
  position: absolute;
  left: 0;
  right: 0;
  height: 54px;
  border-radius: 12px;
  padding: 8px 12px;
  font-size: .72rem;
  color: #fff;
  box-shadow: 0 8px 18px rgba(0,0,0,.55);
  transition: transform .45s cubic-bezier(.3,.9,.3,1);
}

.scd-32__mini .scd-32__lbl {
  color: rgba(255,255,255,.85);
}

.scd-32__mini b {
  font-size: .95rem;
  display: block;
  margin-top: 2px;
}

.scd-32__mini--m1 {
  background: linear-gradient(135deg,#6366f1,#818cf8);
  z-index: 3;
  transform: translateY(0);
}

.scd-32__mini--m2 {
  background: linear-gradient(135deg,#ec4899,#f472b6);
  z-index: 2;
  transform: translateY(8px) scale(.95);
}

.scd-32__mini--m3 {
  background: linear-gradient(135deg,#14b8a6,#2dd4bf);
  z-index: 1;
  transform: translateY(16px) scale(.9);
}

.scd-32__tile--channels:hover .scd-32__mini--m1 {
  transform: translateY(-120px);
}

.scd-32__tile--channels:hover .scd-32__mini--m2 {
  transform: translateY(-58px) scale(1);
}

.scd-32__tile--channels:hover .scd-32__mini--m3 {
  transform: translateY(4px) scale(1);
}

.scd-32__spark {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 34px;
  margin-top: 10px;
}

.scd-32__spark span {
  flex: 1;
  background: linear-gradient(#34d399,#059669);
  border-radius: 3px;
}

.scd-32__glow {
  position: absolute;
  width: 90px;
  height: 90px;
  border-radius: 50%;
  filter: blur(40px);
  opacity: .5;
  top: -20px;
  right: -20px;
}

@media (prefers-reduced-motion: reduce) {
  .scd-32__tile,
    .scd-32__mini {
    transition: none !important;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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: Minimalist Bento Grid Stacked Cards
Source: https://codefronts.com/components/css-stacked-cards/minimalist-bento-grid-stacked-cards/

A dark, dashboard-style bento grid where one tile embeds a stacked mini-card component to conserve space — channel breakdowns sit collapsed inside a single cell and fan open on hover, while neighboring tiles show stats, a sparkline, and glow accents. Built for analytics dashboards and content-dense grids where stacking saves container real estate.
## HTML
```html
<div class="scd-32">
  <div class="scd-32__stage">
    <div class="scd-32__tile scd-32__tile--tall scd-32__tile--channels">
      <span class="scd-32__lbl">Channels</span>
      <div class="scd-32__substack">
        <div class="scd-32__mini scd-32__mini--m1"><span class="scd-32__lbl">Organic</span><b>62%</b></div>
        <div class="scd-32__mini scd-32__mini--m2"><span class="scd-32__lbl">Paid</span><b>24%</b></div>
        <div class="scd-32__mini scd-32__mini--m3"><span class="scd-32__lbl">Referral</span><b>14%</b></div>
      </div>
    </div>
    <div class="scd-32__tile scd-32__tile--wide"><div class="scd-32__glow" style="background:#34d399"></div><span class="scd-32__lbl">Revenue</span><div class="scd-32__val">$48.2k <small>+12%</small></div><div class="scd-32__spark"><span style="height:40%"></span><span style="height:55%"></span><span style="height:45%"></span><span style="height:70%"></span><span style="height:60%"></span><span style="height:85%"></span><span style="height:100%"></span></div></div>
    <div class="scd-32__tile"><span class="scd-32__lbl">Users</span><div class="scd-32__val">9.1k</div></div>
    <div class="scd-32__tile"><span class="scd-32__lbl">Churn</span><div class="scd-32__val" style="color:#fca5a5">1.8%</div></div>
    <div class="scd-32__tile"><div class="scd-32__glow" style="background:#818cf8"></div><span class="scd-32__lbl">NPS</span><div class="scd-32__val">72</div></div>
  </div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&display=swap');

.scd-32,
.scd-32 *,
.scd-32 *::before,
.scd-32 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.scd-32 {
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  background: #0e0f13;
  font-family: 'Geist', sans-serif;
  padding: 20px;
}

.scd-32__stage {
  display: grid;
  grid-template-columns: repeat(3, 118px);
  grid-template-rows: repeat(3, 118px);
  gap: 12px;
}

.scd-32__tile {
  background: #191b22;
  border: 1px solid #262934;
  border-radius: 18px;
  padding: 16px;
  position: relative;
  overflow: hidden;
  transition: border-color .3s;
}

.scd-32__tile:hover {
  border-color: #3a4050;
}

.scd-32__lbl {
  font-size: .68rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #6b7280;
}

.scd-32__val {
  font-size: 1.6rem;
  font-weight: 700;
  color: #f3f4f6;
  margin-top: 4px;
}

.scd-32__val small {
  font-size: .8rem;
  color: #34d399;
}

.scd-32__tile--wide {
  grid-column: span 2;
}

.scd-32__tile--tall {
  grid-row: span 2;
}

.scd-32__tile--channels {
  overflow: visible;
  z-index: 5;
}

.scd-32__tile--channels:hover {
  z-index: 20;
}

.scd-32__substack {
  position: absolute;
  bottom: 14px;
  left: 16px;
  right: 16px;
  height: 54px;
}

.scd-32__mini {
  position: absolute;
  left: 0;
  right: 0;
  height: 54px;
  border-radius: 12px;
  padding: 8px 12px;
  font-size: .72rem;
  color: #fff;
  box-shadow: 0 8px 18px rgba(0,0,0,.55);
  transition: transform .45s cubic-bezier(.3,.9,.3,1);
}

.scd-32__mini .scd-32__lbl {
  color: rgba(255,255,255,.85);
}

.scd-32__mini b {
  font-size: .95rem;
  display: block;
  margin-top: 2px;
}

.scd-32__mini--m1 {
  background: linear-gradient(135deg,#6366f1,#818cf8);
  z-index: 3;
  transform: translateY(0);
}

.scd-32__mini--m2 {
  background: linear-gradient(135deg,#ec4899,#f472b6);
  z-index: 2;
  transform: translateY(8px) scale(.95);
}

.scd-32__mini--m3 {
  background: linear-gradient(135deg,#14b8a6,#2dd4bf);
  z-index: 1;
  transform: translateY(16px) scale(.9);
}

.scd-32__tile--channels:hover .scd-32__mini--m1 {
  transform: translateY(-120px);
}

.scd-32__tile--channels:hover .scd-32__mini--m2 {
  transform: translateY(-58px) scale(1);
}

.scd-32__tile--channels:hover .scd-32__mini--m3 {
  transform: translateY(4px) scale(1);
}

.scd-32__spark {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 34px;
  margin-top: 10px;
}

.scd-32__spark span {
  flex: 1;
  background: linear-gradient(#34d399,#059669);
  border-radius: 3px;
}

.scd-32__glow {
  position: absolute;
  width: 90px;
  height: 90px;
  border-radius: 50%;
  filter: blur(40px);
  opacity: .5;
  top: -20px;
  right: -20px;
}

@media (prefers-reduced-motion: reduce) {
  .scd-32__tile,
    .scd-32__mini {
    transition: none !important;
  }
}
```

How this works

A CSS Grid dashboard layout using named grid areas — grid-template-areas: 'primary primary sidebar' 'stats sparkline sidebar' — with one cell embedding a stacked mini-card component. That cell contains 3-4 collapsed sub-cards stacked with slight offset; on hover the stack fans open to reveal each channel breakdown.

Zero JavaScript. The stack fan-out is pure CSS :hover triggering transform:translateY on each sub-card.

Sibling tiles show stats (large numeric readouts), a sparkline (inline SVG mini-chart), and glow accents (radial-gradient overlays). The whole bento reads as a dashboard preview — the pattern Vercel, Framer, Linear, Notion, and premium SaaS landing pages ship.

Make it yours

  • Rebrand each tile from the CSS variables on .scd-32 — dark-mode default, but a light-mode variant works with inverted contrast.
  • Change the grid template to add or remove tiles — the layout auto-flows.
  • Adjust the stacked sub-cards' fan distance via translateY in each child rule.
  • Add real data to the sparkline via inline SVG <path> coordinates.
  • For dashboard mockups, populate the stats with real numbers relevant to your product (MRR, active users, conversion rate).

Gotchas — read before shipping

  • Bento grids are trend-coded (2023-2025) — they can date fast if used for evergreen products.
  • The stacked mini-cards should not intercept clicks on the parent tile — set pointer-events:none on decorative sub-cards.
  • Ensure text contrast within each tile — dashboard backgrounds vary in luminance, so test each tile's text against its actual background.
  • For real dashboards, connect the stats to real data — hardcoded &ldquo;$47,283&rdquo; that never changes reads as a placeholder.
  • Sparkline SVGs must have aria-hidden="true" or a text description via <title> child — decorative charts should be hidden from screen readers.

Browser support

ChromeSafariFirefoxEdge
57+10.1+52+57+

CSS Grid with named areas and inline SVG are universally supported.

Techniques used in this demo

Search CodeFronts

Loading…