Journal

How to Create Sticky Stacking Cards in Shopify (Scroll Effect, 2026)

The stacking-cards effect — where each card scrolls up, sticks in place, and the next one slides over it like a deck being dealt — looks like an expensive animation. It isn't. The core is a single CSS property, position: sticky, with no JavaScript and no app. The polish on top (cards scaling down as they get buried, so the stack reads as depth) is a few more lines of native CSS.

This is a focused, copy-paste tutorial for Online Store 2.0 themes. If you want the broader picture first — CSS vs Intersection Observer vs GSAP — read how to add scroll animations to Shopify without an app; this post zooms into one effect and ships it.

The short answer

Wrap each card in a tall container and give the card position: sticky; top: 0. As you scroll, each card pins to the top of the viewport while the next container scrolls up and overlaps it. Stagger the top value (or add a small scale-down) so the buried cards recede instead of stacking dead flat. That's the whole effect, and it works in every modern browser with zero JavaScript.

Step 1 — The markup

A wrapper, then one "card" per panel. The structure is deliberately plain so it drops into any theme.

<section class="stack">
  <div class="stack__card">
    <h2>Card one</h2>
    <p>Your first story panel.</p>
  </div>
  <div class="stack__card">
    <h2>Card two</h2>
    <p>This one slides up and over card one.</p>
  </div>
  <div class="stack__card">
    <h2>Card three</h2>
    <p>And so on, as deep as you like.</p>
  </div>
</section>

Step 2 — The CSS that does the stacking

This is the part people overcomplicate. position: sticky plus a shared top is the entire mechanism.

.stack__card {
  position: sticky;
  top: 0;
  min-height: 100vh;       /* each card fills the viewport while pinned */
  display: grid;
  place-content: center;
  border-radius: 16px;
  /* give each card its own background so the overlap is visible */
}

/* Alternate colors just so you can see the stacking while testing */
.stack__card:nth-child(odd)  { background: #14110f; color: #f4efe9; }
.stack__card:nth-child(even) { background: #1e1916; color: #f4efe9; }

That alone gives you cards that pin and overlap. Each card sticks at top: 0, and because the next card is a later sibling, it scrolls up and covers the pinned one.

The depth trick: stagger the top value so each card pins a little lower than the last, leaving a sliver of the previous card peeking out — that's what makes it read as a physical stack rather than a slideshow. The clean way is a per-card custom property:

<div class="stack__card" style="--i:0">…</div>
<div class="stack__card" style="--i:1">…</div>
<div class="stack__card" style="--i:2">…</div>
.stack__card {
  position: sticky;
  top: calc(2rem + var(--i) * 1.5rem); /* each card pins 1.5rem lower */
}

Step 3 — Add scale-down depth (native, no JavaScript)

To make buried cards recede, shrink each one as it gets pinned. In 2026 you can do this with native CSS scroll-driven animation — no library, runs off the main thread:

@keyframes sink {
  to { transform: scale(0.92); }
}

@supports (animation-timeline: view()) {
  .stack__card {
    animation: sink linear both;
    animation-timeline: view();
    /* scale down only over the portion where it's leaving the top */
    animation-range: exit 0% exit 100%;
    transform-origin: center top;
  }
}

@media (prefers-reduced-motion: reduce) {
  .stack__card { animation: none; transform: none; }
}

view() ties the scale to the card's own position in the viewport, so it shrinks exactly as the next card buries it. Browsers without scroll-driven support (Firefox today) simply skip the scale and keep the clean sticky stack — still a working effect, which is why the @supports guard matters.

Step 4 — Paste it into your Shopify theme

Two safe homes in an Online Store 2.0 theme (Dawn or any theme built on it):

Quick, single page — Custom Liquid block:

  1. Admin → Online Store → Themes → Customize.
  2. On the target page, Add section → Custom Liquid.
  3. Paste the markup and a <style> block with the CSS, then save.

Reusable across the store — a section file:

  1. Admin → Online Store → Themes → ⋯ → Edit code.
  2. Create sections/stacking-cards.liquid, add the markup, a {% stylesheet %} block, and a {% schema %} so each card becomes a merchant-editable block in the theme editor.

Either way: duplicate your live theme first (Themes → ⋯ → Duplicate), build and test on the copy, then publish. There's no undo on live code edits.

One Shopify-specific gotcha: position: sticky silently fails if any ancestor has overflow: hidden or overflow: clip. Many themes set that on section wrappers. If your cards refuse to stick, that's almost always why — check the parent containers in your theme's CSS.

Keep it fast and accessible

Sticky stacking is one of the cheapest scroll effects there is — position: sticky is handled by the browser's compositor and costs almost nothing. Keep it that way:

  • Don't animate layout. The scale-down uses transform, which is GPU-composited. Never animate width, height, or top on a per-frame basis.
  • Reserve the height. Each card already has min-height: 100vh, so the page height is stable and you won't get a Cumulative Layout Shift penalty.
  • Honor reduced motion. The prefers-reduced-motion block above turns off the scale for users who asked for less motion; the sticky stack itself remains, which is fine — pinning is not vestibular-triggering motion the way parallax is.
  • Lazy-load card images. If your cards carry imagery, add loading="lazy" to everything below the fold so the stack doesn't block your Largest Contentful Paint.

When to reach for the done-for-you version

The CSS above gets you a clean, performant stack. Where hand-rolling gets expensive is the signature version: a scrubbed timeline where text, image, and background transition in sync as each card pins, tuned easing, and an authored reduced-motion and no-JS fallback. That's GSAP ScrollTrigger territory, and it's real engineering to build and maintain through theme updates.

If you want that grade of effect without writing and owning it, our Sticky Cards section is exactly this — story cards that stack and swap as shoppers scroll, engineered and performance-gated as a single drop-in file. You can try it live with your own content before you buy, no app and no subscription. Use the CSS in this post when a clean stack is enough; reach for the section when you want the polished, narrative version.

FAQ

Do you need JavaScript for stacking cards? No. The stacking itself is pure CSS — position: sticky with a shared top. JavaScript (or native scroll-driven animation) is only needed for extras like scaling buried cards, and even that can now be done in CSS.

Why aren't my sticky cards sticking on Shopify? The most common cause is an ancestor element with overflow: hidden or overflow: clip, which disables position: sticky for everything inside it. Many themes apply this to section wrappers — inspect the parent containers and remove or override it.

Does the stacking-cards effect hurt Core Web Vitals? Not if built with CSS. position: sticky is composited by the browser and very cheap. Give each card a fixed min-height to avoid layout shift and lazy-load below-the-fold images, and the effect is effectively free.

Will it work in Safari and Firefox? The sticky stacking works in every modern browser. The optional native scale-down (animation-timeline: view()) works in Chrome, Edge, and Safari 18+; Firefox skips it gracefully thanks to the @supports guard, keeping the clean stack.

Can I make stacking cards in Shopify without editing theme code? Yes — paste the markup and CSS into a Custom Liquid block from the theme editor. You only need the code editor if you want a reusable, merchant-configurable section.