01 · Find the signal
Turn scattered feedback into one clear direction
Bring customer notes, product evidence, and commercial context into a shared view. The strongest signal rises without hiding the detail behind it.
01 / 04
A free stacked cards scroll animation for React with restrained depth and a complete static fallback.
The story, layer by layer
Follow the route from first signal to lasting insight. Each chapter settles into place while the complete story stays readable.
01 · Find the signal
Bring customer notes, product evidence, and commercial context into a shared view. The strongest signal rises without hiding the detail behind it.
01 / 04
02 · Shape the route
Frame the opportunity, assign ownership, and connect each dependency before work begins. The route stays legible as the story gathers depth.
02 / 04
03 · Move together
See what is moving, what needs attention, and where the next decision sits. Teams keep their own rhythm while sharing one dependable operating picture.
03 / 04
04 · Close the loop
Connect outcomes back to the original signal so each launch sharpens the next one. The full story remains present, ordered, and ready to revisit.
04 / 04
<ScrollStackedCards
title="A product story that builds layer by layer"
description="Follow one readable route from signal to insight."
cards={[
{
id: "signal",
eyebrow: "01 · Find the signal",
title: "Turn feedback into one clear direction",
description:
"Bring customer evidence into a shared view.",
visual: <div aria-hidden="true">Signal map</div>,
},
{
id: "shape",
eyebrow: "02 · Shape the route",
title: "Give every decision a visible next move",
description:
"Connect each dependency before work begins.",
visual: <div aria-hidden="true">Workflow preview</div>,
},
{
id: "learn",
eyebrow: "03 · Close the loop",
title: "Carry the evidence into what comes next",
description:
"Connect outcomes back to the original signal.",
visual: <div aria-hidden="true">Outcome preview</div>,
},
]}
/>Scroll Stacked Cards is a free stacked cards scroll animation for React, Next.js, and Tailwind. Three to seven substantial story cards settle into a CSS-sticky stack while scoped GSAP ScrollTriggers add restrained scale, rotation, and opacity depth to the cards already covered.
The section keeps native scrolling, semantic order, and every card's complete copy intact. On mobile, with reduced motion, or without JavaScript, the ordered list becomes a normal static layout with no transforms, inert content, or extended scroll range.
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/scroll-stacked-cardsimport { ScrollStackedCards } from "@/components/scroll-stacked-cards";
const cards = [
{
id: "signal",
eyebrow: "01 · Find the signal",
title: "Turn feedback into one clear direction",
description: "Bring customer evidence into a shared view.",
visual: <div aria-hidden="true">Signal map</div>,
},
{
id: "shape",
eyebrow: "02 · Shape the route",
title: "Give every decision a visible next move",
description: "Connect each dependency before work begins.",
visual: <div aria-hidden="true">Workflow preview</div>,
},
{
id: "learn",
eyebrow: "03 · Close the loop",
title: "Carry the evidence into what comes next",
description: "Connect outcomes back to the original signal.",
visual: <div aria-hidden="true">Outcome preview</div>,
},
];
export default function Page() {
return (
<ScrollStackedCards
title="A product story that builds layer by layer"
description="Follow one readable route from signal to insight."
cards={cards}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow | string | "The story, layer by layer" | Introductory label rendered above the section heading. |
| title | string | required | Section heading rendered as the component's single h2. |
| description | string | undefined | Optional supporting section copy. |
| cards | { id: string; eyebrow?: string; title: string; description: string; visual?: ReactNode }[] | required | Three to seven ordered story cards with stable ids, complete copy, and optional consumer-owned visuals. |
| stickyOffset | number | 88 | First-card desktop sticky offset in CSS pixels, clamped from 64 to 144. |
| overlap | number | 18 | Per-card desktop sticky offset in CSS pixels, clamped from 8 to 32. |
| scaleFalloff | number | 0.035 | Scale lost for each covered depth, clamped from 0 to 0.07. |
| rotation | number | 1.2 | Alternating maximum rotation in degrees, clamped from 0 to 3. |
| scrub | number | 0.4 | ScrollTrigger catch-up duration in seconds, clamped from 0.1 to 1.1. |
| cardMinHeight | number | 420 | Card minimum height in CSS pixels, clamped from 320 to 620. |
| radius | number | 28 | Card corner radius in CSS pixels, clamped from 12 to 40. |
| className | string | undefined | Additional classes merged onto the section root. |
Scroll Stacked Cards exposes three Tier 3 colour tokens. --scroll-stack-surface controls each card, --scroll-stack-visual controls the visual well, and --scroll-stack-accent colours visual highlights. Geometry and motion are controlled through the numeric props in the playground:
:root {
--scroll-stack-surface: var(--background);
--scroll-stack-visual: var(--background);
--scroll-stack-accent: var(--ring);
}