Sticky panel stack
Sequential panels that each stick to the viewport while the next one slides up over them, like cards being dealt onto a pile.
Grade: ARuntimes: css · gsapStatus: live
Loading demo…
Intent
Turns a linear list of three to five ideas into a paced sequence. Each panel gets the reader's full attention for a fixed scroll distance, and the overlap makes the transition between ideas feel authored rather than incidental.
Implementation
`--panel-index` drives z-index, so adding a panel means adding one attribute rather than editing a stylesheet.
Dependencies: none
<section class="stack">
<div class="stack__slot" style="--panel-index: 0">
<article class="stack__panel">…</article>
</div>
<div class="stack__slot" style="--panel-index: 1">
<article class="stack__panel">…</article>
</div>
<div class="stack__slot" style="--panel-index: 2">
<article class="stack__panel">…</article>
</div>
</section>
<style>
/* No overflow clipping anywhere in the ancestor chain, or sticky breaks. */
.stack { display: grid; }
.stack__slot {
/* The slot supplies scroll distance; the panel inside stays pinned. */
height: 200svh;
z-index: var(--panel-index);
position: relative;
}
.stack__panel {
position: sticky;
top: 0;
min-height: 100svh;
display: grid;
align-content: center;
gap: var(--space-md);
padding: var(--space-xl) var(--gutter);
background: var(--bg);
border-block-start: 1px solid var(--line);
}
</style>Use it when
- Three to five steps in a process, or three to five product pillars.
- When the items are peers and the order matters.
Avoid it when
- With more than five panels — the section becomes a scroll tax.
- When any panel's content is taller than the viewport, since the sticky panel will clip it.
Accessibility
- This is pure CSS sticky, so it degrades to a normal stacked list — that is the reduced-motion behaviour and it needs no extra handling.
- Ensure each panel's content fits within `100svh` at the smallest supported width, or it becomes unreachable.
- Keyboard focus moving into an off-screen panel must scroll it into view; do not use `overflow: hidden` on the wrapper.
Performance
- Zero JavaScript, zero scroll listeners.
- Avoid `backdrop-filter` on the panels — compositing a full-viewport blur on every frame of a sticky scroll is the most common cause of jank in this pattern.
Knobs
- scroll per panel
- Wrapper height beyond the sticky child. Default: 100svh
- peek
- How much of the previous panel stays visible. Default: 0
Composition
Conflicts with
Instruction for Claude Code
Build a sticky panel stack: each panel sits in a 200svh slot with position relative and a z-index from a --panel-index custom property; the panel itself is position sticky at top 0 with min-height 100svh and an opaque background. Do not put overflow hidden or clip on any ancestor. Keep panel content shorter than one viewport. Use no JavaScript and no backdrop-filter.