Art Tech Overlay Navigation
Goal
Build a fullscreen overlay navigation for an editorial/tech studio site. The star effect: clicking a burger button plays a single paused GSAP timeline that reveals a black fullscreen overlay by wiping eight vertical blocks downward via animated clip-path (staggered, power3.inOut), and — overlapping the tail of that wipe — fades in a menu title plus a list of menu items. Clicking again reverses the exact same timeline to close.
Tech
Vanilla HTML/CSS/JS with ES module imports. Use gsap (npm) only — no plugins, no ScrollTrigger, no smooth-scroll library. Google Font Space Mono (weights 400 & 700) loaded via <link>.
Layout / HTML
Body contains four top-level regions, in this DOM order (order matters for stacking):
.website-content— fixed, full viewport,z-index: 0. Holds a single.headerdiv with an<img>of the wide wordmark. This is the background "page" behind everything.nav— fixed, full width,z-index: 2(sits ABOVE the overlay so the burger stays clickable). Three flex children, eachflex: 1:.logo→<img>of the small square brand mark..logo-main→<img>of the wide wordmark, centered..toggle-btn→ a<button class="burger">aligned to the right. The button has an inlineonclick="this.classList.toggle('active');"that toggles the CSS X-morph (this is separate from the GSAP handler)..overlay— fixed, full viewport,display: flex. Contains exactly 8<div class="block">siblings, no content inside..overlay-menu— fixed, full viewport, flex column centered, white text. Contains:.menu-title→<p>[menu]</p>- four
.menu-itemrows, each with three parts:.menu-item-year(<p>),.menu-item-name(<p>),.menu-item-link(<a href="#">[explore]</a>).
Menu content (year / name / link), top to bottom:
2023/Digital Art Collecting/[explore]2022/Art NFT Collecting/[explore]2021/Collectors Edition/[explore]Learn More/About/[explore]
Styling
Palette:
- Page background:
#2f24f2(electric indigo/blue). - Overlay blocks:
#000solid black. - Text & links:
#fff.
Typography:
- Global
panda:Space Mono,text-transform: uppercase,font-size: 14px. .menu-item-name p: a large display face — use a bold/condensed technical sans (original uses "PP Formula"; if unavailable let it fall back to a heavy sans-serif). Size4vw,text-align: center.img { width:100%; height:100%; object-fit:cover; }globally.
Key positioning / sizing:
.website-content .header:width: 800px, absolutely centered (top/left: 50%+translate(-50%,-50%))..logo img:width: 100px..logo-main img:width: 300px, centered in its flex cell..toggle-btn:justify-content: flex-end,padding: 0 1.5em.navhaspadding: 0 1em,display:flex,justify-content: space-between,align-items:center.
Burger button (.burger):
display:flex; justify-content:center; align-items:center; padding: 1.5em 2em; height:20px; width:28px; background: rgba(255,255,255,0.25); border-radius:0.25em; border:none; cursor:pointer; transition: all 250ms ease-out;- Two bars via
::beforeand::after: eachwidth:28px; height:1.5px; position:absolute; background:#fff; transition: all 250ms ease-out; will-change: transform;.::beforeistranslateY(-3px),::afteristranslateY(3px). .active.burger::before→translateY(0) rotate(45deg);.active.burger::after→translateY(0) rotate(-45deg)(morphs to an X).:hover→ background becomes solid whitergba(255,255,255,1), and the two bars turn black#000.
Overlay blocks (.block):
flex: 1; height: 100%; background: #000; margin-right: -2px;(the negative margin hides seams between blocks).- Initial
clip-path: polygon(0 0, 100% 0, 100% 0, 0 0)— all four vertices collapsed onto the TOP edge, so the block has zero visible height (hidden at the top). - The
.overlayitself isdisplay:flexso the 8 blocks split the width into 8 equal vertical columns.
Overlay menu (.overlay-menu):
padding: 10em 5em; flex-direction: column; justify-content: center; align-items: center;.menu-titleand every.menu-item:flex: 1; width: 100%; opacity: 0;(start invisible — GSAP fades them in)..menu-item:display:flex; padding:1em; cursor:pointer; transition: 0.3s;. Children flex ratios:.menu-item-year=flex:1,.menu-item-name=flex:3(centered),.menu-item-link=flex:1right-aligned..menu-title: flex-centered.- No
z-indexon.overlay-menu; it stacks above.overlaypurely by DOM order, and belownav(which isz-index:2).
GSAP effect (be exhaustive)
Trigger: click on .burger. State tracked by a boolean isOpen (starts false).
Build ONE timeline, created paused:
const timeline = gsap.timeline({ paused: true });
Tween 1 — block wipe (added first):
- Targets:
.block(all 8). - Animate
clipPath→"polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)"(full rectangle). Because CSS starts the blocks collapsed at the top edge, this wipes each block DOWNWARD to full height. duration: 1stagger: 0.075(blocks reveal left → right, 75ms apart).ease: "power3.inOut".
Tween 2 — menu fade (added second, overlapping):
- Targets:
".menu-title, .menu-item"(1 title + 4 items = 5 elements). - Animate
opacity→1. duration: 0.3stagger: 0.05.- Position parameter:
"-=0.5"— this tween starts 0.5s before the previous tween ends, so the text begins fading in while the last blocks are still wiping down.
Click handler on .burger:
toggleButton.addEventListener("click", () => {
isOpen ? timeline.reverse() : timeline.play();
isOpen = !isOpen;
});
So the first click .play()s (open), the next .reverse()s (close, running the exact same timeline backward — blocks retract upward and text fades out), and so on. Wrap everything in DOMContentLoaded.
Note the burger's active X-morph is driven independently by the inline onclick toggling the .active class (pure CSS transition), firing on the same click as the GSAP handler.
Assets / images
Two images, both flat white graphics on transparent backgrounds (no real brand names — use a neutral studio wordmark):
- Wide wordmark lockup (roughly 4:1, landscape) — white letterforms of a studio name. Used twice: as the big centered background logo (in
.header, 800px wide) and as the centered logo in the nav bar (300px wide). - Small square brand mark (1:1) — a compact white monogram/glyph. Used as the top-left nav logo (100px wide).
Behavior notes
- Desktop-first. At
max-width: 900px: hide the centered.logo-main img(display:none) and shrink the background.headertowidth: 300px. - The timeline is fully reversible and idempotent — repeated open/close clicks just play/reverse the same instance.
- No scroll interaction, no canvas, no WebGL; lightweight and mobile-safe.