Scroll Curtain Reveal — Free GSAP ScrollTrigger Snippet
Scroll Curtain Reveal · Scroll · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Scroll Curtain Reveal — Lift a Panel to Uncover the Section Behind

The scroll curtain reveal is the transition where a full-screen panel slides up and off the top of the viewport as you scroll, drawing back like a theater curtain to reveal the content waiting behind it — a dramatic way to move between sections. This snippet builds it with GSAP and ScrollTrigger (from a CDN), plus plain HTML and CSS.
A covering panel over hidden content
The stage layers two pieces in the same box: a background section at the base and a full-cover .cr-curtain panel above it at z-index: 2. At rest the curtain hides the section completely. The entire effect is simply sliding that one panel up out of the way — the reveal is what's already sitting underneath.
Pinned, scrubbed lift
A GSAP timeline tied to a pinned ScrollTrigger (scrub: true, end: '+=130%') drives the curtain. From position 0, the curtain tweens yPercent: -100, moving it entirely off the top edge, while its inner label fades and lifts slightly ahead of the panel so the text doesn't ride awkwardly to the very top. Because it's pinned and scrubbed, the curtain rises exactly as far as you scroll and lowers again if you scroll back — a fully reversible draw.
The content settles as it's revealed
The background heading starts pushed down and dim, then eases into place over the same scroll (from at timeline position 0.2). So as the curtain lifts, the revealed section doesn't just sit there statically — its headline rises into focus, making the reveal feel like the content is arriving rather than being uncovered by a moving shutter. Layering the curtain exit and the content entrance on one timeline keeps them synchronized.
Why yPercent and a pin
yPercent: -100 is a transform, so the curtain slides on the GPU without reflowing the page, and transform-origin: top keeps the motion anchored upward. Pinning the stage means the lift plays over a deliberate scroll distance instead of the panel simply scrolling away with the page — that control is what makes it read as a designed transition rather than normal scrolling.
Linear and contained
ease: 'none' on the curtain and content tweens locks them to the scrollbar with no rubber-banding, and overflow: hidden on the stage clips the curtain as it exits so nothing spills above the section. The whole thing runs backward perfectly on scroll-up.
Customizing it
Change the lift direction (curtain down with yPercent: 100, or sideways), the reveal distance via end, the panel styling, or what's behind it — an image, a hero, a video. Pair it with scroll split panels, a scroll image mask, or a scroll zoom hero.
Build with AI
Build, Understand, Optimize, and Extend It With AI
You don't have to trace the layering and timing by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why the curtain and its inner label are tweened as two separate targets with a slight timing offset, and why yPercent is used instead of animating top or margin-top for the lift. The same assistant can help optimize it — asking whether pinning for +=130% is the right scroll distance for a heavier background (like a full-bleed video) behind the curtain, or whether the settling-content tween needs its own trigger for very tall reveal sections. It's also useful for extending the effect: ask it to make the curtain lift sideways instead of up, split it into two panels that part like real theater curtains, or drop a video or image behind it instead of a gradient and heading. Treat the code less like a finished artifact and more like a starting point for a conversation.
Prompt to recreate it
Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:
Build a "scroll curtain reveal" effect in plain HTML, CSS, and JavaScript using GSAP and its ScrollTrigger plugin (load both from a CDN, no build step).
Requirements:
- A single stage section with overflow hidden, containing two absolutely-positioned full-cover layers: a background layer with the "revealed" content sitting underneath, and a curtain layer on top (higher z-index) that fully hides the background at rest.
- Build one GSAP timeline tied to a pinned, scrubbed ScrollTrigger (pin: true, scrub: true) on the stage, running for a fixed extra scroll distance (e.g. +=130% of the viewport).
- At timeline position 0, tween the curtain's yPercent to -100 so it slides entirely off the top edge using a transform (not top/margin, which would trigger layout), with transform-origin set to the top of the curtain.
- Also starting at position 0, fade and lift the curtain's inner label/text slightly ahead of the curtain's own exit, so the label doesn't awkwardly ride all the way to the very top edge before disappearing.
- Slightly after the curtain starts moving (e.g. at 20% of the timeline), animate the background content's heading in from a lower, dimmer starting state (translateY plus reduced opacity) up to its resting state, so the revealed section doesn't just sit there statically — it settles into focus in sync with the curtain lifting.
- Use ease: 'none' on every tween in the timeline so all motion tracks the scrollbar linearly with no rubber-banding, since the scrub itself provides the smoothing.
- Confirm the whole sequence reverses correctly on scroll-up (curtain lowers back down, heading recedes) purely from the scrub being tied to scroll position, with no separate reverse-specific code.Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.
Step by step
How to Use
- 1Add the GSAP CDNsInclude gsap and ScrollTrigger from the CDN panel.
- 2Paste HTML, CSS, and JSA curtain panel covers a hidden section.
- 3Scroll downThe curtain slides up off the top.
- 4See the revealThe section behind settles into focus.
- 5Scroll back upThe curtain lowers — motion is scrubbed.
- 6Change the contentPut any hero or media behind the curtain.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
The stage layers a background section at the base and a full-cover curtain panel above it at z-index 2, so at rest the curtain hides the section completely. The whole effect is sliding that one panel up out of the way — the reveal is the content already sitting underneath it.
A GSAP timeline on a pinned ScrollTrigger with scrub: true tweens the curtain to yPercent -100, moving it off the top edge, while its label fades and lifts slightly ahead. Because it is pinned and scrubbed, the curtain rises exactly as far as you scroll and lowers again on scroll-up — a fully reversible draw.
The background heading starts pushed down and dim, then eases into place over the same scroll via a from tween at timeline position 0.2. So as the curtain lifts, the section's headline arrives rather than sitting static, and layering the curtain exit and the content entrance on one timeline keeps them synchronized.
yPercent is a transform, so the curtain slides on the GPU without reflowing the page, with transform-origin: top anchoring the motion upward. Pinning makes the lift play over a deliberate scroll distance instead of the panel just scrolling away with the page, which is what makes it read as a designed transition.
In a mount effect, register ScrollTrigger and build the pinned, scrubbed timeline scoped to refs for the stage, curtain, and content. Return a cleanup that reverts the GSAP context so the pin is removed on unmount and route changes. Put any hero or media behind the curtain; the layered CSS and timeline port unchanged.