Scroll Image Mask — Free GSAP ScrollTrigger Clip-Path Reveal
Scroll Image Mask · Scroll · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Scroll Image Mask — Open an Image From a Slit to Fullscreen

The scroll image mask is the cinematic reveal where an image starts as a thin centered slot and expands to fill the frame as you scroll, while the picture inside subtly un-zooms — the dramatic media reveal from editorial and product launch pages. This snippet builds it with GSAP and ScrollTrigger (from a CDN) using an animated CSS clip-path.
clip-path inset as the mask
The frame's reveal is driven by clip-path: inset(...), which crops the element by a percentage from each edge. At rest it's inset(42% 38%) — cropped heavily top/bottom and left/right, leaving only a small central window. Animating the inset toward inset(0%) un-crops it edge by edge until the whole frame shows. Because clip-path clips rather than resizes, the media behind stays put while the visible window grows, which is exactly the "opening aperture" feel.
A scrubbed, pinned timeline
The stage pins (pin: true) and a scrubbed timeline runs for end: '+=140%', so the aperture opens in direct response to scrolling. Three tweens share position 0-ish: the clip-path opens, the media scales from 1.3 down to 1, and the caption rises in slightly later (at 0.3 on the timeline). ease: 'none' keeps the opening linear so it tracks the scrollbar, and the whole thing reverses on scroll-up.
The counter-zoom
The media starts scaled to 1.3 and eases to 1 as the mask opens. This counter-zoom is a subtle but important touch: as the window expands, the image gently pulls back, so you feel like you're seeing more of the scene rather than the same crop stretched. It mirrors the language of a camera revealing a wider shot.
Why clip-path over width/height
You could animate the frame's width and height, but that reflows layout and resizes the media with it, breaking the aperture illusion. clip-path is a GPU-composited paint operation — it changes only what's visible, not the box, so the image inside holds steady while the mask opens, and there's no layout thrash. will-change: clip-path hints the compositor.
Asset-free demo
The "photo" is layered CSS gradients with a darkening overlay so the caption stays legible. Swap .im-media's background for a real background-image and the reveal is identical, since the timeline only touches clip-path, transform, and opacity.
Customizing it
Change the starting inset for a different slit shape (a horizontal letterbox, a vertical slot), the open distance via end, the counter-zoom amount, or the caption timing. Pair it with a scroll split panels reveal, a scroll zoom hero, or a scroll curtain reveal.
Build with AI
Build, Understand, Optimize, and Extend It With AI
You do not need to puzzle out the clip-path percentages or the counter-zoom math on your own. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to walk through exactly why the frame animates clip-path inset instead of width and height, and why the media layer starts scaled to 1.3 rather than 1. The same assistant is useful for optimizing it — for example checking whether will-change: clip-path is actually helping on lower-end mobile GPUs or whether it should be applied only during the active scroll range. It is just as good for extending the effect: ask it to make the starting slit a horizontal letterbox instead of a centered window, add a second image that cross-fades in as the first mask finishes opening, or drive the reveal from an IntersectionObserver instead of a pin for pages that cannot afford a full ScrollTrigger pin. 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 image mask" reveal in plain HTML, CSS, and JavaScript using GSAP and its ScrollTrigger plugin (load both from a CDN, no build step).
Requirements:
- A pinned stage containing a frame element whose clip-path starts as inset() cropped heavily from all four edges (for example inset(42% 38%) with a rounded corner), leaving only a small centered window, and a media layer inside it that starts scaled up (for example scale(1.3)).
- Register a single GSAP timeline on a ScrollTrigger with pin: true, scrub: true, and an end a percentage of the viewport tall (not the full page), so the reveal completes within a bounded scroll distance.
- Inside that timeline, animate the frame's clip-path inset toward inset(0% 0%) so the window opens edge to edge, and simultaneously animate the media layer's scale back down to 1, so the image appears to un-zoom as the aperture opens. Both tweens must use ease: none and start at the same timeline position so they are perfectly linked to scroll position.
- Add a caption element that animates in (rising up and fading in from 0 opacity) starting partway through the timeline, after the frame has already begun opening, not before.
- Do not animate width or height directly on the frame to achieve the reveal — the cropping must come only from clip-path so the box never reflows and the effect stays GPU-composited.
- The whole sequence must reverse cleanly when the user scrolls back up, closing the aperture and re-zooming the image.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 small image slit sits in a pinned stage.
- 3Scroll downThe slit opens to a fullscreen frame.
- 4Watch the un-zoomThe image pulls back as the window grows.
- 5Scroll back upThe aperture closes — motion is scrubbed.
- 6Use a real imageSet background-image on the media layer.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
The frame uses clip-path: inset(), which crops it by a percentage from each edge. At rest it is inset(42% 38%), leaving a small central window, and the timeline animates the inset toward inset(0%) to un-crop it edge by edge. Because clip-path clips rather than resizes, the media stays put while the visible window grows.
The media starts at scale 1.3 and eases to 1 over the same scroll, a counter-zoom. As the aperture expands, the image gently pulls back so you feel like you are seeing more of the scene rather than the same crop stretched — it mirrors a camera revealing a wider shot, which makes the reveal cinematic.
Animating width and height reflows layout and resizes the media with the box, breaking the aperture illusion and causing layout thrash. clip-path is a GPU-composited paint operation that changes only what is visible, so the image holds steady while the mask opens. will-change: clip-path hints the compositor for smoothness.
The stage pins and the timeline is scrubbed over end: +=140%, so the clip-path open, the counter-zoom, and the caption rise all advance with the scrollbar and reverse on scroll-up. ease: none keeps the opening linear so it tracks scroll position exactly rather than playing on its own clock.
In a mount effect, register ScrollTrigger and build the pinned, scrubbed timeline scoped to refs for the stage, frame, media, and caption. Return a cleanup that reverts the GSAP context so the pin is removed on unmount. Swap the media background for an image; the clip-path CSS and timeline port unchanged. Note older Safari needs -webkit-clip-path.