11 / 28
All 28 in 28 Tailwind Hamburger Menus
- 01Tailwind Hamburger Menu with Clip-Path Circle Expansion
- 02Tailwind Keyboard Navigable Hamburger Menu with ARIA Attributes
- 03Tailwind Animated 3-Line to X Hamburger Icon Toggle
- 04Tailwind Slide-In Off-Canvas Drawer with Dimmed Backdrop Overlay
- 05Pure Tailwind Checkbox Hack Hamburger Navigation (No JavaScript)
- 06Tailwind Responsive Hamburger Menu with Integrated Search Bar & Social Links
- 07Tailwind Glassmorphism Backdrop Blur Hamburger Navigation
- 08Tailwind Push Page Navigation Menu (Off-Canvas Content Shift)
- 09Pure Tailwind Hamburger Menu Without JavaScript
- 10Tailwind Hamburger Menu Morphing to Close Icon Animation
- 11Tailwind Full Screen Mobile Navigation Overlay
- 12Tailwind Slide Out Sidebar Navigation / Off Canvas Menu
- 13Tailwind Responsive Navbar Mobile Hamburger Toggle Breakpoints
- 14Tailwind Minimalist Floating Hamburger Button
- 15Tailwind CSS Responsive Hamburger Menu Component
- 16Tailwind Rebuild of the Bootstrap 5 Navbar Hamburger Toggle
- 17Tailwind WCAG Accessible Hamburger Menu Example
- 18Pure Tailwind Dropdown Slide Down Mobile Hamburger Menu
- 19Simple 3-Line Tailwind Hamburger Icon Hover Effect
- 20Tailwind Full Screen Blur Overlay Hamburger Menu
- 21Tailwind Mobile Bottom Navigation Bar with Floating Hamburger Toggle
- 22Pure Tailwind Multi-Level Accordion Hamburger Dropdown Menu
- 23Flexbox Navbar Right-Aligned Tailwind Hamburger Icon
- 24Radial Ripple Expand Tailwind Hamburger Menu
- 25Sticky Tailwind Navbar Shrinking Hamburger Icon on Scroll
- 26Neumorphic Tailwind Hamburger Toggle Button
- 27Brutalist Design Bordered Tailwind Hamburger Menu
- 28Tailwind 3D Flip Canvas Mobile Hamburger Navigation
Tailwind Full Screen Mobile Navigation Overlay
The fashion-house takeover: the menu becomes the page, and five oversized links reveal themselves line by line from under invisible masks. The technique to steal is two utilities deep — overflow-hidden on the <li>, translate-y-[110%] on the link — and in the port both halves of the reveal sit in the same class list as the stagger that drives them.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="thb-11 w-full min-h-svh grid justify-center content-start @container bg-thb11-paper font-thb11-sans text-thb11-sheet px-5 py-9" aria-label="Fullscreen overlay navigation demo">
<div class="group relative w-[min(400px,88vw)] h-140 rounded-3xl overflow-hidden bg-thb11-paper border border-thb11-edge">
<div class="absolute inset-0 grid content-start gap-4 px-6.5 py-23" aria-hidden="true">
<div class="flex flex-col justify-between h-62.5 p-4.5 rounded bg-linear-[160deg,oklch(0.85_0.02_75),oklch(0.72_0.045_60)]">
<span class="text-[11px] font-bold tracking-[0.3em]">AW·26</span>
<b class="text-[29px] leading-[1.04] font-bold tracking-[-0.02em]">Silhouettes<br>in Static</b>
</div>
<div class="h-2.5 w-[76%] rounded-full bg-thb11-line"></div>
<div class="h-2.5 w-[58%] rounded-full bg-thb11-line"></div>
</div>
<nav id="thb11-sheet" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center px-7.5 bg-thb11-sheet opacity-0 scale-[1.03] invisible [transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_.45s] group-data-open:opacity-100 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_0s]">
<ul class="list-none">
<li style="--i:0" class="overflow-hidden"><a href="#collections" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">01</span>Collections</a></li>
<li style="--i:1" class="overflow-hidden"><a href="#runway" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">02</span>Runway</a></li>
<li style="--i:2" class="overflow-hidden"><a href="#atelier" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">03</span>Atelier</a></li>
<li style="--i:3" class="overflow-hidden"><a href="#stockists" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">04</span>Stockists</a></li>
<li style="--i:4" class="overflow-hidden"><a href="#contact" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">05</span>Contact</a></li>
</ul>
<footer class="flex items-baseline gap-4.5 mt-8.5 text-xs text-thb11-mut opacity-0 transition-[opacity] duration-400 group-data-open:opacity-100 group-data-open:delay-500">
<a href="#instagram" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Instagram</a>
<a href="#pinterest" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Pinterest</a>
<span class="ml-auto">Paris — Tokyo</span>
</footer>
</nav>
<header class="absolute inset-x-0 top-0 z-3 flex items-center justify-between h-18 px-5.5 mix-blend-difference text-thb11-paper">
<span class="text-[15px] font-extrabold tracking-[0.34em]">VESTIGE</span>
<button type="button" aria-expanded="false" aria-controls="thb11-sheet" class="flex items-center gap-3 min-h-11 border-0 bg-transparent text-inherit cursor-pointer font-thb11-sans text-xs font-semibold tracking-[0.18em] uppercase focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 focus-visible:rounded">
<span class="relative block h-[15px] overflow-hidden">
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Menu</i>
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Close</i>
</span>
<span class="relative block w-6.5 h-2.5" aria-hidden="true">
<b class="absolute left-0 top-0 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:translate-y-1 group-data-open:rotate-20 motion-reduce:transition-none"></b>
<b class="absolute left-0 top-2 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:-translate-y-1 group-data-open:-rotate-20 motion-reduce:transition-none"></b>
</span>
</button>
</header>
</div>
</section><section class="thb-11 w-full min-h-svh grid justify-center content-start @container bg-thb11-paper font-thb11-sans text-thb11-sheet px-5 py-9" aria-label="Fullscreen overlay navigation demo">
<div class="group relative w-[min(400px,88vw)] h-140 rounded-3xl overflow-hidden bg-thb11-paper border border-thb11-edge">
<div class="absolute inset-0 grid content-start gap-4 px-6.5 py-23" aria-hidden="true">
<div class="flex flex-col justify-between h-62.5 p-4.5 rounded bg-linear-[160deg,oklch(0.85_0.02_75),oklch(0.72_0.045_60)]">
<span class="text-[11px] font-bold tracking-[0.3em]">AW·26</span>
<b class="text-[29px] leading-[1.04] font-bold tracking-[-0.02em]">Silhouettes<br>in Static</b>
</div>
<div class="h-2.5 w-[76%] rounded-full bg-thb11-line"></div>
<div class="h-2.5 w-[58%] rounded-full bg-thb11-line"></div>
</div>
<nav id="thb11-sheet" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center px-7.5 bg-thb11-sheet opacity-0 scale-[1.03] invisible [transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_.45s] group-data-open:opacity-100 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_0s]">
<ul class="list-none">
<li style="--i:0" class="overflow-hidden"><a href="#collections" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">01</span>Collections</a></li>
<li style="--i:1" class="overflow-hidden"><a href="#runway" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">02</span>Runway</a></li>
<li style="--i:2" class="overflow-hidden"><a href="#atelier" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">03</span>Atelier</a></li>
<li style="--i:3" class="overflow-hidden"><a href="#stockists" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">04</span>Stockists</a></li>
<li style="--i:4" class="overflow-hidden"><a href="#contact" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">05</span>Contact</a></li>
</ul>
<footer class="flex items-baseline gap-4.5 mt-8.5 text-xs text-thb11-mut opacity-0 transition-[opacity] duration-400 group-data-open:opacity-100 group-data-open:delay-500">
<a href="#instagram" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Instagram</a>
<a href="#pinterest" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Pinterest</a>
<span class="ml-auto">Paris — Tokyo</span>
</footer>
</nav>
<header class="absolute inset-x-0 top-0 z-3 flex items-center justify-between h-18 px-5.5 mix-blend-difference text-thb11-paper">
<span class="text-[15px] font-extrabold tracking-[0.34em]">VESTIGE</span>
<button type="button" aria-expanded="false" aria-controls="thb11-sheet" class="flex items-center gap-3 min-h-11 border-0 bg-transparent text-inherit cursor-pointer font-thb11-sans text-xs font-semibold tracking-[0.18em] uppercase focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 focus-visible:rounded">
<span class="relative block h-[15px] overflow-hidden">
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Menu</i>
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Close</i>
</span>
<span class="relative block w-6.5 h-2.5" aria-hidden="true">
<b class="absolute left-0 top-0 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:translate-y-1 group-data-open:rotate-20 motion-reduce:transition-none"></b>
<b class="absolute left-0 top-2 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:-translate-y-1 group-data-open:-rotate-20 motion-reduce:transition-none"></b>
</span>
</button>
</header>
</div>
</section>@import "tailwindcss";
@theme {
--color-thb11-paper: #f3f1eb;
--color-thb11-paper: oklch(0.95 0.007 80);
--color-thb11-sheet: #24211d;
--color-thb11-sheet: oklch(0.16 0.012 70);
--color-thb11-edge: #dcd8d0;
--color-thb11-edge: oklch(0.86 0.01 80);
--color-thb11-line: #dfdbd3;
--color-thb11-line: oklch(0.87 0.012 80);
--color-thb11-mut: #918b81;
--color-thb11-mut: oklch(0.6 0.015 70);
--color-thb11-acc: #dbab4e;
--color-thb11-acc: oklch(0.78 0.15 75);
--font-thb11-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb11-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb11: cubic-bezier(0.2, 0.75, 0.15, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-11 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb11-paper: #f3f1eb;
--color-thb11-paper: oklch(0.95 0.007 80);
--color-thb11-sheet: #24211d;
--color-thb11-sheet: oklch(0.16 0.012 70);
--color-thb11-edge: #dcd8d0;
--color-thb11-edge: oklch(0.86 0.01 80);
--color-thb11-line: #dfdbd3;
--color-thb11-line: oklch(0.87 0.012 80);
--color-thb11-mut: #918b81;
--color-thb11-mut: oklch(0.6 0.015 70);
--color-thb11-acc: #dbab4e;
--color-thb11-acc: oklch(0.78 0.15 75);
--font-thb11-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb11-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb11: cubic-bezier(0.2, 0.75, 0.15, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-11 {
width: 100%;
min-height: 100svh;
}(function () {
document.querySelectorAll('.thb-11 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb11-sheet"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();(function () {
document.querySelectorAll('.thb-11 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb11-sheet"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-thb11-paper: #f3f1eb;
--color-thb11-paper: oklch(0.95 0.007 80);
--color-thb11-sheet: #24211d;
--color-thb11-sheet: oklch(0.16 0.012 70);
--color-thb11-edge: #dcd8d0;
--color-thb11-edge: oklch(0.86 0.01 80);
--color-thb11-line: #dfdbd3;
--color-thb11-line: oklch(0.87 0.012 80);
--color-thb11-mut: #918b81;
--color-thb11-mut: oklch(0.6 0.015 70);
--color-thb11-acc: #dbab4e;
--color-thb11-acc: oklch(0.78 0.15 75);
--font-thb11-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb11-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb11: cubic-bezier(0.2, 0.75, 0.15, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-11 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb11-paper: #f3f1eb;
--color-thb11-paper: oklch(0.95 0.007 80);
--color-thb11-sheet: #24211d;
--color-thb11-sheet: oklch(0.16 0.012 70);
--color-thb11-edge: #dcd8d0;
--color-thb11-edge: oklch(0.86 0.01 80);
--color-thb11-line: #dfdbd3;
--color-thb11-line: oklch(0.87 0.012 80);
--color-thb11-mut: #918b81;
--color-thb11-mut: oklch(0.6 0.015 70);
--color-thb11-acc: #dbab4e;
--color-thb11-acc: oklch(0.78 0.15 75);
--font-thb11-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb11-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb11: cubic-bezier(0.2, 0.75, 0.15, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-11 {
width: 100%;
min-height: 100svh;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The mask reveal survives the port intact and reads better for it:
overflow-hiddenon the item,translate-y-[110%]andgroup-data-open:translate-y-0on the link. Three utilities, no rules. - The asymmetric choreography becomes self-documenting. The delay is only in the
group-data-open:half, so anyone reading the markup can see that closing has no stagger. - The
::beforeindex number becomes a realaria-hiddenspan. It also carries its own[-webkit-text-stroke:0], since the parent's stroke would otherwise outline the numerals too. mix-blend-mode:differenceand-webkit-text-strokeboth become arbitrary utilities — correct, since neither is a design-scale value, and both stay attached to the element that needs them.- The
cqitype clamp needs the stage to be a container, which is one@containerutility on the section rather than acontainer-typerule. - The word-swap box (Menu / Close) keeps its 15px geometry as arbitrary values, because the height, the line-height and the translate must agree exactly — a spacing-scale value would drift.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Full Screen Mobile Navigation Overlay
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/tailwind-full-screen-mobile-navigation-overlay/
The fashion-house takeover: the menu becomes the page, and five oversized links reveal themselves line by line from under invisible masks. The technique to steal is two utilities deep — overflow-hidden on the <li>, translate-y-[110%] on the link — and in the port both halves of the reveal sit in the same class list as the stagger that drives them.
## HTML
```html
<section class="thb-11 w-full min-h-svh grid justify-center content-start @container bg-thb11-paper font-thb11-sans text-thb11-sheet px-5 py-9" aria-label="Fullscreen overlay navigation demo">
<div class="group relative w-[min(400px,88vw)] h-140 rounded-3xl overflow-hidden bg-thb11-paper border border-thb11-edge">
<div class="absolute inset-0 grid content-start gap-4 px-6.5 py-23" aria-hidden="true">
<div class="flex flex-col justify-between h-62.5 p-4.5 rounded bg-linear-[160deg,oklch(0.85_0.02_75),oklch(0.72_0.045_60)]">
<span class="text-[11px] font-bold tracking-[0.3em]">AW·26</span>
<b class="text-[29px] leading-[1.04] font-bold tracking-[-0.02em]">Silhouettes<br>in Static</b>
</div>
<div class="h-2.5 w-[76%] rounded-full bg-thb11-line"></div>
<div class="h-2.5 w-[58%] rounded-full bg-thb11-line"></div>
</div>
<nav id="thb11-sheet" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center px-7.5 bg-thb11-sheet opacity-0 scale-[1.03] invisible [transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_.45s] group-data-open:opacity-100 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_0s]">
<ul class="list-none">
<li style="--i:0" class="overflow-hidden"><a href="#collections" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">01</span>Collections</a></li>
<li style="--i:1" class="overflow-hidden"><a href="#runway" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">02</span>Runway</a></li>
<li style="--i:2" class="overflow-hidden"><a href="#atelier" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">03</span>Atelier</a></li>
<li style="--i:3" class="overflow-hidden"><a href="#stockists" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">04</span>Stockists</a></li>
<li style="--i:4" class="overflow-hidden"><a href="#contact" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">05</span>Contact</a></li>
</ul>
<footer class="flex items-baseline gap-4.5 mt-8.5 text-xs text-thb11-mut opacity-0 transition-[opacity] duration-400 group-data-open:opacity-100 group-data-open:delay-500">
<a href="#instagram" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Instagram</a>
<a href="#pinterest" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Pinterest</a>
<span class="ml-auto">Paris — Tokyo</span>
</footer>
</nav>
<header class="absolute inset-x-0 top-0 z-3 flex items-center justify-between h-18 px-5.5 mix-blend-difference text-thb11-paper">
<span class="text-[15px] font-extrabold tracking-[0.34em]">VESTIGE</span>
<button type="button" aria-expanded="false" aria-controls="thb11-sheet" class="flex items-center gap-3 min-h-11 border-0 bg-transparent text-inherit cursor-pointer font-thb11-sans text-xs font-semibold tracking-[0.18em] uppercase focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 focus-visible:rounded">
<span class="relative block h-[15px] overflow-hidden">
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Menu</i>
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Close</i>
</span>
<span class="relative block w-6.5 h-2.5" aria-hidden="true">
<b class="absolute left-0 top-0 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:translate-y-1 group-data-open:rotate-20 motion-reduce:transition-none"></b>
<b class="absolute left-0 top-2 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:-translate-y-1 group-data-open:-rotate-20 motion-reduce:transition-none"></b>
</span>
</button>
</header>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb11-paper: #f3f1eb;
--color-thb11-paper: oklch(0.95 0.007 80);
--color-thb11-sheet: #24211d;
--color-thb11-sheet: oklch(0.16 0.012 70);
--color-thb11-edge: #dcd8d0;
--color-thb11-edge: oklch(0.86 0.01 80);
--color-thb11-line: #dfdbd3;
--color-thb11-line: oklch(0.87 0.012 80);
--color-thb11-mut: #918b81;
--color-thb11-mut: oklch(0.6 0.015 70);
--color-thb11-acc: #dbab4e;
--color-thb11-acc: oklch(0.78 0.15 75);
--font-thb11-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb11-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb11: cubic-bezier(0.2, 0.75, 0.15, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-11 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.thb-11 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb11-sheet"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Full Screen Mobile Navigation Overlay
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/tailwind-full-screen-mobile-navigation-overlay/
The fashion-house takeover: the menu becomes the page, and five oversized links reveal themselves line by line from under invisible masks. The technique to steal is two utilities deep — overflow-hidden on the <li>, translate-y-[110%] on the link — and in the port both halves of the reveal sit in the same class list as the stagger that drives them.
## HTML
```html
<section class="thb-11 w-full min-h-svh grid justify-center content-start @container bg-thb11-paper font-thb11-sans text-thb11-sheet px-5 py-9" aria-label="Fullscreen overlay navigation demo">
<div class="group relative w-[min(400px,88vw)] h-140 rounded-3xl overflow-hidden bg-thb11-paper border border-thb11-edge">
<div class="absolute inset-0 grid content-start gap-4 px-6.5 py-23" aria-hidden="true">
<div class="flex flex-col justify-between h-62.5 p-4.5 rounded bg-linear-[160deg,oklch(0.85_0.02_75),oklch(0.72_0.045_60)]">
<span class="text-[11px] font-bold tracking-[0.3em]">AW·26</span>
<b class="text-[29px] leading-[1.04] font-bold tracking-[-0.02em]">Silhouettes<br>in Static</b>
</div>
<div class="h-2.5 w-[76%] rounded-full bg-thb11-line"></div>
<div class="h-2.5 w-[58%] rounded-full bg-thb11-line"></div>
</div>
<nav id="thb11-sheet" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center px-7.5 bg-thb11-sheet opacity-0 scale-[1.03] invisible [transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_.45s] group-data-open:opacity-100 group-data-open:scale-100 group-data-open:visible group-data-open:[transition:opacity_.35s,scale_.45s_var(--ease-thb11),visibility_0s_0s]">
<ul class="list-none">
<li style="--i:0" class="overflow-hidden"><a href="#collections" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">01</span>Collections</a></li>
<li style="--i:1" class="overflow-hidden"><a href="#runway" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">02</span>Runway</a></li>
<li style="--i:2" class="overflow-hidden"><a href="#atelier" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">03</span>Atelier</a></li>
<li style="--i:3" class="overflow-hidden"><a href="#stockists" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">04</span>Stockists</a></li>
<li style="--i:4" class="overflow-hidden"><a href="#contact" class="block py-1.75 text-[clamp(34px,9cqi,44px)] font-extrabold leading-[1.08] tracking-[-0.02em] uppercase no-underline text-transparent [-webkit-text-stroke:1.5px_var(--color-thb11-paper)] translate-y-[110%] transition-[translate,color] duration-600 ease-thb11 hover:text-thb11-paper focus-visible:text-thb11-paper focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)] motion-reduce:duration-150"><span class="align-super mr-2 text-xs font-semibold tracking-[0.2em] text-thb11-acc [-webkit-text-stroke:0]" aria-hidden="true">05</span>Contact</a></li>
</ul>
<footer class="flex items-baseline gap-4.5 mt-8.5 text-xs text-thb11-mut opacity-0 transition-[opacity] duration-400 group-data-open:opacity-100 group-data-open:delay-500">
<a href="#instagram" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Instagram</a>
<a href="#pinterest" class="pb-0.5 text-thb11-paper no-underline border-b border-[oklch(1_0_0/0.25)] transition-[color,border-color] duration-200 hover:text-thb11-acc hover:border-thb11-acc focus-visible:text-thb11-acc focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-2">Pinterest</a>
<span class="ml-auto">Paris — Tokyo</span>
</footer>
</nav>
<header class="absolute inset-x-0 top-0 z-3 flex items-center justify-between h-18 px-5.5 mix-blend-difference text-thb11-paper">
<span class="text-[15px] font-extrabold tracking-[0.34em]">VESTIGE</span>
<button type="button" aria-expanded="false" aria-controls="thb11-sheet" class="flex items-center gap-3 min-h-11 border-0 bg-transparent text-inherit cursor-pointer font-thb11-sans text-xs font-semibold tracking-[0.18em] uppercase focus-visible:outline-2 focus-visible:outline-thb11-acc focus-visible:outline-offset-4 focus-visible:rounded">
<span class="relative block h-[15px] overflow-hidden">
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Menu</i>
<i class="block h-[15px] leading-[15px] not-italic transition-[translate] duration-400 ease-thb11 group-data-open:-translate-y-[15px]">Close</i>
</span>
<span class="relative block w-6.5 h-2.5" aria-hidden="true">
<b class="absolute left-0 top-0 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:translate-y-1 group-data-open:rotate-20 motion-reduce:transition-none"></b>
<b class="absolute left-0 top-2 w-6.5 h-[1.5px] bg-current transition-[translate,rotate] duration-350 ease-thb11 group-data-open:-translate-y-1 group-data-open:-rotate-20 motion-reduce:transition-none"></b>
</span>
</button>
</header>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb11-paper: #f3f1eb;
--color-thb11-paper: oklch(0.95 0.007 80);
--color-thb11-sheet: #24211d;
--color-thb11-sheet: oklch(0.16 0.012 70);
--color-thb11-edge: #dcd8d0;
--color-thb11-edge: oklch(0.86 0.01 80);
--color-thb11-line: #dfdbd3;
--color-thb11-line: oklch(0.87 0.012 80);
--color-thb11-mut: #918b81;
--color-thb11-mut: oklch(0.6 0.015 70);
--color-thb11-acc: #dbab4e;
--color-thb11-acc: oklch(0.78 0.15 75);
--font-thb11-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb11-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb11: cubic-bezier(0.2, 0.75, 0.15, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh. It scopes the demo, and it holds the stage at full height in the
moment before the browser build has compiled its utilities. */
.thb-11 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.thb-11 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb11-sheet"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
}
btn.addEventListener('click', function () { set(btn.getAttribute('aria-expanded') !== 'true'); });
stage.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && stage.hasAttribute('data-open')) { set(false); btn.focus(); }
});
});
})();
```How this works
Every award-site reveal is this one trick. A clipping box and a child parked fully outside it:
<li class="overflow-hidden">
<a class="block translate-y-[110%]
transition-[translate] duration-600 ease-thb11
group-data-open:translate-y-0
group-data-open:[transition-delay:calc(250ms+var(--i)*70ms)]">…</a>
</li>Because the parent clips, the link is invisible until it climbs into the box — no opacity involved, which is why the edge looks razor-sharp, like typesetting rather than fading. 110% rather than 100% hides descenders.
Sequencing beats simultaneity. The sheet fades in over 350ms while the links take 600ms with a 70ms cascade: the paper arrives, then the type is printed onto it.
Why the delay lives only in the open half. Utilities make this choreography visible. The resting class list has no delay, so on close every link leaves at once while the sheet fades — the professional default, and in the CSS version it is an easy thing to get accidentally wrong.
Outlined type needs scale. At clamp(34px,9cqi,44px) a 1.5px stroke is legible; at body sizes it would shimmer. The cqi term is what makes the type track the component, so the same markup works in a phone frame and a full-bleed hero.
Make it yours
- Type scale is one clamp:
text-[clamp(34px,9cqi,44px)]. Thecqiterm resizes with the component — keep the stage@container-typed. - Stagger direction: feed
--iin reverse for a bottom-up reveal, or scatter the values for a ransom-note entrance. - The index numbers are real
aria-hiddenspans, so restyling or deleting them never touches the link's accessible name. - Sheet mood: swap
--color-thb11-sheetforoklch(0.93 0.02 90)and the ink token for the gallery version — paper sheet, dark type. - Stroke weight lives in the arbitrary
[-webkit-text-stroke:…]; thinner than 1px shimmers on non-retina screens.
Gotchas — read before shipping
- The mask must be on the
<li>, not the<ul>. One shared mask makes every link appear at once and kills the per-line typesetting illusion. translate-y-[110%]does nothing on an inline element — the link needsblockinside its mask.-webkit-text-strokeis prefixed in every engine including Firefox; write it as an arbitrary property exactly as spelled, and pair it withtext-transparentor nothing shows.- Full-viewport overlays need
min-h-dvhin production, nevermin-h-svhalone if the last link must clear mobile browser chrome — and never100vh, which overshoots. mix-blend-differenceneeds a stacking context to blend against; the stage's own background provides it, but an opaque wrapper between them kills the effect.- Keep the stagger delay OUT of the resting class list, or closing plays the cascade backwards and feels sluggish.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Overflow masks, translate transitions and -webkit-text-stroke run everywhere back to 2020; cqi units need Chrome 105, Safari 16 and Firefox 110, and degrade gracefully through the clamp bounds.