Curtain Menu Overlay
A fullscreen nav overlay that arrives as layered clip-path curtains, oversized type masking up on a stagger, and a preview plate that wipes in the direction you moved.
About This Effect
The award-site fullscreen menu, built as a real component rather than a showreel. Three curtain panels sweep across the page on offset durations and eases, so the overlay arrives with depth instead of landing as one flat colour, and the oversized link type masks up behind them on a stagger that is choreographed against the sweep rather than queued after it.
Read the full effect overview
Moving through the list drives four things at once: the hovered link slides out and takes the accent, the rest dim and recede, an anchored preview plate wipes to that link's image in the direction you travelled, and a colour bloom behind the type re-tints and drifts to the row. Sweep the list fast and the transitions compress and the plate leans into the movement, because each new preview finishes the one in flight instead of joining a queue.
Closing is a genuine reverse: the type retreats from the bottom of the list up, the preview folds away, and only then do the curtains lift, deepest layer first, so the accent is the last thing off the screen.
What's Included
- Three-layer clip-path curtain with per-layer duration, ease and offset, so the overlay arrives with depth rather than as one flat panel
- Oversized link type revealed through real overflow masks on a stagger keyed to the curtain, using labelled GSAP timelines you can retime in one place
- Anchored preview plate that wipes between links from the direction the pointer travelled, with a velocity-scaled lean and elastic settle
- Interruption-safe transitions: a wipe caught mid-flight is completed, not abandoned, so a fast sweep down the list never queues a backlog
- One input, four responses: active link shifts and takes the link's tint, siblings dim and recede, the preview wipes, and a background bloom re-tints and drifts to the row
- Magnetic close control with a lagging glyph and an elastic release
- Real dialog behaviour: focus trap, Escape to close, aria-expanded and aria-hidden, inert while closed, and focus returned to the trigger
- Body scroll lock that also stops and restarts Lenis, which ignores overflow: hidden
- Keyboard focus drives the same preview channel as hover, and press-and-slide does on touch
- Progressive enhancement: without JavaScript the whole menu renders as an ordinary nav list, so no link is ever trapped behind a class the script never added
Perfect For
- Agency, studio and portfolio sites where the menu is part of the brand rather than a utility
- Fashion, architecture and photography sites that want a per-section image preview in the nav
- Product and campaign microsites needing one memorable transition between a handful of pages
- Editorial and magazine sites where section names carry display type worth showing at full size
- Any mobile-first site that wants a fullscreen nav designed at 390px rather than shrunk into it
How It Works
The curtains are three absolutely positioned panels animated from inset(0% 0% 100% 0%) to inset(0% 0% 0% 0%) at staggered times with different durations and eases. Writing both ends as full inset() rectangles is what keeps GSAP interpolating geometry instead of falling back to a stylesheet's clip-path: none. The link labels are their own overflow masks, with the moving child created by the script, so a buyer's markup stays one span per link; the reveal tweens yPercent and y together, which is what stops a masked line settling permanently offset.
The preview channel is deliberately not an image trail. Where an image-trail effect (effect 021) spawns a pool of cards that follow the cursor and decay, this is a single plate anchored in the layout with two stacked images that swap roles. Each change writes the new source to whichever image is underneath, clips it to the edge the pointer came from, and wipes it open while the outgoing one drifts the other way. If a change arrives mid-wipe the in-flight image is snapped to complete first, so the layer order is always known and a rapid sweep produces one clean transition per link rather than a stack of half-drawn frames.
Switch speed is measured between requests and normalised into a rush value that shortens the wipe and increases the frame's velocity lean, which then springs back on an elastic ease. The same setActive call drives the link stack, the caption and the colour bloom, so hover, keyboard focus and a finger sliding down the list all produce identical results.
Everything runs inside gsap.context() and gsap.matchMedia(), with listeners in a Map for teardown. Under prefers-reduced-motion the overlay still opens, but as a plain cross-fade with every start state restored in CSS, and the magnetic close is never wired up.