01 / 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 Hamburger Menu with Clip-Path Circle Expansion
The reveal every design-award site uses, ported to variants: tap the burger and the menu grows out of the button as a perfect circle, because the panel carries its closed and open clip-path as two arbitrary utilities on one element. The state is a data-open attribute on the stage, so the panel, the icon bars and the link stagger all read it through group-data-open: — the stylesheet keeps nothing but tokens.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="thb-01 w-full min-h-svh grid justify-center content-start bg-thb01-bg font-thb01-sans text-thb01-ink px-5 py-9" aria-label="Clip-path circle expansion hamburger menu demo">
<div class="group relative w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb01-bg border border-thb01-edge shadow-[0_30px_60px_-35px_oklch(0.3_0.05_285/0.45)]">
<header class="relative z-1 flex items-center h-19 px-6">
<span class="flex items-center gap-2.5 text-[15px] font-bold tracking-[-0.01em]">
<i class="w-5.5 h-5.5 rounded-full bg-[conic-gradient(from_210deg,var(--color-thb01-acc),oklch(0.55_0.2_300),var(--color-thb01-acc))]" aria-hidden="true"></i>orbit.studio
</span>
</header>
<div class="grid gap-3.5 px-6 pt-2" aria-hidden="true">
<div class="h-47 mb-2 rounded-2xl bg-linear-[140deg,oklch(0.9_0.03_265),oklch(0.84_0.05_300)]"></div>
<div class="h-3 w-[82%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[64%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[74%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[46%] rounded-full bg-thb01-line"></div>
</div>
<nav id="thb01-menu" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center gap-1.5 px-8.5 bg-[radial-gradient(120%_100%_at_100%_0%,oklch(0.3_0.08_295),var(--color-thb01-menu)_55%)] invisible [clip-path:circle(0px_at_calc(100%-46px)_46px)] [transition:clip-path_.65s_var(--ease-thb01),visibility_0s_.65s] group-data-open:visible group-data-open:[clip-path:circle(150%_at_calc(100%-46px)_46px)] group-data-open:[transition:clip-path_.65s_var(--ease-thb01),visibility_0s_0s] motion-reduce:[clip-path:none] motion-reduce:opacity-0 motion-reduce:[transition:opacity_.15s,visibility_0s_.15s] motion-reduce:group-data-open:opacity-100 motion-reduce:group-data-open:[transition:opacity_.15s]">
<a href="#work" style="--i:0" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">01</small>Work</a>
<a href="#studio" style="--i:1" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">02</small>Studio</a>
<a href="#journal" style="--i:2" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">03</small>Journal</a>
<a href="#contact" style="--i:3" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">04</small>Contact</a>
<p style="--i:4" class="mt-6.5 font-thb01-mono text-xs text-thb01-dim opacity-0 translate-y-4.5 transition-[opacity,translate] duration-400 ease-thb01 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">hello@orbit.studio · NYC — LDN</p>
</nav>
<button type="button" aria-expanded="false" aria-controls="thb01-menu" aria-label="Open menu" class="absolute z-3 top-5.5 right-5.5 grid place-items-center w-12 h-12 rounded-full border-0 bg-thb01-ink cursor-pointer transition-[background,scale] duration-300 hover:scale-106 active:scale-94 focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-3 group-data-open:bg-thb01-btnopen motion-reduce:transition-none">
<span class="relative block w-5 h-3.5" aria-hidden="true">
<i class="absolute left-0 top-0 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:translate-y-1.5 group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-1.5 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[opacity,translate] duration-200 group-data-open:opacity-0 group-data-open:-translate-x-1.5 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-3 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:-translate-y-1.5 group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</div>
</section><section class="thb-01 w-full min-h-svh grid justify-center content-start bg-thb01-bg font-thb01-sans text-thb01-ink px-5 py-9" aria-label="Clip-path circle expansion hamburger menu demo">
<div class="group relative w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb01-bg border border-thb01-edge shadow-[0_30px_60px_-35px_oklch(0.3_0.05_285/0.45)]">
<header class="relative z-1 flex items-center h-19 px-6">
<span class="flex items-center gap-2.5 text-[15px] font-bold tracking-[-0.01em]">
<i class="w-5.5 h-5.5 rounded-full bg-[conic-gradient(from_210deg,var(--color-thb01-acc),oklch(0.55_0.2_300),var(--color-thb01-acc))]" aria-hidden="true"></i>orbit.studio
</span>
</header>
<div class="grid gap-3.5 px-6 pt-2" aria-hidden="true">
<div class="h-47 mb-2 rounded-2xl bg-linear-[140deg,oklch(0.9_0.03_265),oklch(0.84_0.05_300)]"></div>
<div class="h-3 w-[82%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[64%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[74%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[46%] rounded-full bg-thb01-line"></div>
</div>
<nav id="thb01-menu" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center gap-1.5 px-8.5 bg-[radial-gradient(120%_100%_at_100%_0%,oklch(0.3_0.08_295),var(--color-thb01-menu)_55%)] invisible [clip-path:circle(0px_at_calc(100%-46px)_46px)] [transition:clip-path_.65s_var(--ease-thb01),visibility_0s_.65s] group-data-open:visible group-data-open:[clip-path:circle(150%_at_calc(100%-46px)_46px)] group-data-open:[transition:clip-path_.65s_var(--ease-thb01),visibility_0s_0s] motion-reduce:[clip-path:none] motion-reduce:opacity-0 motion-reduce:[transition:opacity_.15s,visibility_0s_.15s] motion-reduce:group-data-open:opacity-100 motion-reduce:group-data-open:[transition:opacity_.15s]">
<a href="#work" style="--i:0" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">01</small>Work</a>
<a href="#studio" style="--i:1" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">02</small>Studio</a>
<a href="#journal" style="--i:2" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">03</small>Journal</a>
<a href="#contact" style="--i:3" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">04</small>Contact</a>
<p style="--i:4" class="mt-6.5 font-thb01-mono text-xs text-thb01-dim opacity-0 translate-y-4.5 transition-[opacity,translate] duration-400 ease-thb01 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">hello@orbit.studio · NYC — LDN</p>
</nav>
<button type="button" aria-expanded="false" aria-controls="thb01-menu" aria-label="Open menu" class="absolute z-3 top-5.5 right-5.5 grid place-items-center w-12 h-12 rounded-full border-0 bg-thb01-ink cursor-pointer transition-[background,scale] duration-300 hover:scale-106 active:scale-94 focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-3 group-data-open:bg-thb01-btnopen motion-reduce:transition-none">
<span class="relative block w-5 h-3.5" aria-hidden="true">
<i class="absolute left-0 top-0 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:translate-y-1.5 group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-1.5 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[opacity,translate] duration-200 group-data-open:opacity-0 group-data-open:-translate-x-1.5 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-3 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:-translate-y-1.5 group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</div>
</section>@import "tailwindcss";
@theme {
--color-thb01-bg: #f7f7fa;
--color-thb01-bg: oklch(0.97 0.005 250);
--color-thb01-ink: #2c2f3d;
--color-thb01-ink: oklch(0.22 0.02 260);
--color-thb01-edge: #dfe0e6;
--color-thb01-edge: oklch(0.88 0.01 260);
--color-thb01-line: #e4e4ea;
--color-thb01-line: oklch(0.9 0.008 260);
--color-thb01-menu: #2f2549;
--color-thb01-menu: oklch(0.23 0.06 285);
--color-thb01-btnopen: #453a63;
--color-thb01-btnopen: oklch(0.32 0.07 295);
--color-thb01-paper: #f6f5f0;
--color-thb01-paper: oklch(0.96 0.01 90);
--color-thb01-dim: #a49ab5;
--color-thb01-dim: oklch(0.68 0.03 290);
--color-thb01-acc: #e5b45c;
--color-thb01-acc: oklch(0.8 0.16 85);
--font-thb01-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb01-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb01: cubic-bezier(0.65, 0, 0.35, 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-01 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb01-bg: #f7f7fa;
--color-thb01-bg: oklch(0.97 0.005 250);
--color-thb01-ink: #2c2f3d;
--color-thb01-ink: oklch(0.22 0.02 260);
--color-thb01-edge: #dfe0e6;
--color-thb01-edge: oklch(0.88 0.01 260);
--color-thb01-line: #e4e4ea;
--color-thb01-line: oklch(0.9 0.008 260);
--color-thb01-menu: #2f2549;
--color-thb01-menu: oklch(0.23 0.06 285);
--color-thb01-btnopen: #453a63;
--color-thb01-btnopen: oklch(0.32 0.07 295);
--color-thb01-paper: #f6f5f0;
--color-thb01-paper: oklch(0.96 0.01 90);
--color-thb01-dim: #a49ab5;
--color-thb01-dim: oklch(0.68 0.03 290);
--color-thb01-acc: #e5b45c;
--color-thb01-acc: oklch(0.8 0.16 85);
--font-thb01-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb01-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb01: cubic-bezier(0.65, 0, 0.35, 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-01 {
width: 100%;
min-height: 100svh;
}(function () {
document.querySelectorAll('.thb-01 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb01-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
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-01 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb01-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
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-thb01-bg: #f7f7fa;
--color-thb01-bg: oklch(0.97 0.005 250);
--color-thb01-ink: #2c2f3d;
--color-thb01-ink: oklch(0.22 0.02 260);
--color-thb01-edge: #dfe0e6;
--color-thb01-edge: oklch(0.88 0.01 260);
--color-thb01-line: #e4e4ea;
--color-thb01-line: oklch(0.9 0.008 260);
--color-thb01-menu: #2f2549;
--color-thb01-menu: oklch(0.23 0.06 285);
--color-thb01-btnopen: #453a63;
--color-thb01-btnopen: oklch(0.32 0.07 295);
--color-thb01-paper: #f6f5f0;
--color-thb01-paper: oklch(0.96 0.01 90);
--color-thb01-dim: #a49ab5;
--color-thb01-dim: oklch(0.68 0.03 290);
--color-thb01-acc: #e5b45c;
--color-thb01-acc: oklch(0.8 0.16 85);
--font-thb01-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb01-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb01: cubic-bezier(0.65, 0, 0.35, 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-01 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb01-bg: #f7f7fa;
--color-thb01-bg: oklch(0.97 0.005 250);
--color-thb01-ink: #2c2f3d;
--color-thb01-ink: oklch(0.22 0.02 260);
--color-thb01-edge: #dfe0e6;
--color-thb01-edge: oklch(0.88 0.01 260);
--color-thb01-line: #e4e4ea;
--color-thb01-line: oklch(0.9 0.008 260);
--color-thb01-menu: #2f2549;
--color-thb01-menu: oklch(0.23 0.06 285);
--color-thb01-btnopen: #453a63;
--color-thb01-btnopen: oklch(0.32 0.07 295);
--color-thb01-paper: #f6f5f0;
--color-thb01-paper: oklch(0.96 0.01 90);
--color-thb01-dim: #a49ab5;
--color-thb01-dim: oklch(0.68 0.03 290);
--color-thb01-acc: #e5b45c;
--color-thb01-acc: oklch(0.8 0.16 85);
--font-thb01-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb01-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb01: cubic-bezier(0.65, 0, 0.35, 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-01 {
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.
- Eight
[data-open] .xrules collapse intogroupon the stage plusgroup-data-open:on the panel, the three icon bars, the button background and the links. The open state is now readable from each element in isolation. group-data-open:is the boolean attribute form — no brackets, no value. Reach forgroup-data-[state=open]:only when the attribute actually carries a value.- The delayed
visibilityneeds the arbitrary[transition:...]shorthand: Tailwind'sdelay-*scale applies one delay to all transitioned properties, and this pattern needs 650ms on one and 0ms on the other. - Four
:nth-childstagger rules become one utility reading--ifrom the element. Adding a fifth link means copying an<a>and incrementing a number. - The
@media (prefers-reduced-motion)block becomesmotion-reduce:variants inline — the circle is dropped with[clip-path:none]and the reveal becomes a 150ms fade. - The webfonts load as
<link>tags insetup, not as an@importin the stylesheet: Tailwind emits user@importrules after its own@layerblocks, where the browser drops them.
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 Hamburger Menu with Clip-Path Circle Expansion
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/tailwind-hamburger-menu-clip-path-circle-expansion/
The reveal every design-award site uses, ported to variants: tap the burger and the menu grows out of the button as a perfect circle, because the panel carries its closed and open clip-path as two arbitrary utilities on one element. The state is a data-open attribute on the stage, so the panel, the icon bars and the link stagger all read it through group-data-open: — the stylesheet keeps nothing but tokens.
## HTML
```html
<section class="thb-01 w-full min-h-svh grid justify-center content-start bg-thb01-bg font-thb01-sans text-thb01-ink px-5 py-9" aria-label="Clip-path circle expansion hamburger menu demo">
<div class="group relative w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb01-bg border border-thb01-edge shadow-[0_30px_60px_-35px_oklch(0.3_0.05_285/0.45)]">
<header class="relative z-1 flex items-center h-19 px-6">
<span class="flex items-center gap-2.5 text-[15px] font-bold tracking-[-0.01em]">
<i class="w-5.5 h-5.5 rounded-full bg-[conic-gradient(from_210deg,var(--color-thb01-acc),oklch(0.55_0.2_300),var(--color-thb01-acc))]" aria-hidden="true"></i>orbit.studio
</span>
</header>
<div class="grid gap-3.5 px-6 pt-2" aria-hidden="true">
<div class="h-47 mb-2 rounded-2xl bg-linear-[140deg,oklch(0.9_0.03_265),oklch(0.84_0.05_300)]"></div>
<div class="h-3 w-[82%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[64%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[74%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[46%] rounded-full bg-thb01-line"></div>
</div>
<nav id="thb01-menu" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center gap-1.5 px-8.5 bg-[radial-gradient(120%_100%_at_100%_0%,oklch(0.3_0.08_295),var(--color-thb01-menu)_55%)] invisible [clip-path:circle(0px_at_calc(100%-46px)_46px)] [transition:clip-path_.65s_var(--ease-thb01),visibility_0s_.65s] group-data-open:visible group-data-open:[clip-path:circle(150%_at_calc(100%-46px)_46px)] group-data-open:[transition:clip-path_.65s_var(--ease-thb01),visibility_0s_0s] motion-reduce:[clip-path:none] motion-reduce:opacity-0 motion-reduce:[transition:opacity_.15s,visibility_0s_.15s] motion-reduce:group-data-open:opacity-100 motion-reduce:group-data-open:[transition:opacity_.15s]">
<a href="#work" style="--i:0" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">01</small>Work</a>
<a href="#studio" style="--i:1" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">02</small>Studio</a>
<a href="#journal" style="--i:2" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">03</small>Journal</a>
<a href="#contact" style="--i:3" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">04</small>Contact</a>
<p style="--i:4" class="mt-6.5 font-thb01-mono text-xs text-thb01-dim opacity-0 translate-y-4.5 transition-[opacity,translate] duration-400 ease-thb01 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">hello@orbit.studio · NYC — LDN</p>
</nav>
<button type="button" aria-expanded="false" aria-controls="thb01-menu" aria-label="Open menu" class="absolute z-3 top-5.5 right-5.5 grid place-items-center w-12 h-12 rounded-full border-0 bg-thb01-ink cursor-pointer transition-[background,scale] duration-300 hover:scale-106 active:scale-94 focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-3 group-data-open:bg-thb01-btnopen motion-reduce:transition-none">
<span class="relative block w-5 h-3.5" aria-hidden="true">
<i class="absolute left-0 top-0 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:translate-y-1.5 group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-1.5 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[opacity,translate] duration-200 group-data-open:opacity-0 group-data-open:-translate-x-1.5 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-3 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:-translate-y-1.5 group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb01-bg: #f7f7fa;
--color-thb01-bg: oklch(0.97 0.005 250);
--color-thb01-ink: #2c2f3d;
--color-thb01-ink: oklch(0.22 0.02 260);
--color-thb01-edge: #dfe0e6;
--color-thb01-edge: oklch(0.88 0.01 260);
--color-thb01-line: #e4e4ea;
--color-thb01-line: oklch(0.9 0.008 260);
--color-thb01-menu: #2f2549;
--color-thb01-menu: oklch(0.23 0.06 285);
--color-thb01-btnopen: #453a63;
--color-thb01-btnopen: oklch(0.32 0.07 295);
--color-thb01-paper: #f6f5f0;
--color-thb01-paper: oklch(0.96 0.01 90);
--color-thb01-dim: #a49ab5;
--color-thb01-dim: oklch(0.68 0.03 290);
--color-thb01-acc: #e5b45c;
--color-thb01-acc: oklch(0.8 0.16 85);
--font-thb01-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb01-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb01: cubic-bezier(0.65, 0, 0.35, 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-01 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.thb-01 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb01-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
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 Hamburger Menu with Clip-Path Circle Expansion
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/tailwind-hamburger-menu-clip-path-circle-expansion/
The reveal every design-award site uses, ported to variants: tap the burger and the menu grows out of the button as a perfect circle, because the panel carries its closed and open clip-path as two arbitrary utilities on one element. The state is a data-open attribute on the stage, so the panel, the icon bars and the link stagger all read it through group-data-open: — the stylesheet keeps nothing but tokens.
## HTML
```html
<section class="thb-01 w-full min-h-svh grid justify-center content-start bg-thb01-bg font-thb01-sans text-thb01-ink px-5 py-9" aria-label="Clip-path circle expansion hamburger menu demo">
<div class="group relative w-[min(400px,88vw)] h-135 rounded-3xl overflow-hidden bg-thb01-bg border border-thb01-edge shadow-[0_30px_60px_-35px_oklch(0.3_0.05_285/0.45)]">
<header class="relative z-1 flex items-center h-19 px-6">
<span class="flex items-center gap-2.5 text-[15px] font-bold tracking-[-0.01em]">
<i class="w-5.5 h-5.5 rounded-full bg-[conic-gradient(from_210deg,var(--color-thb01-acc),oklch(0.55_0.2_300),var(--color-thb01-acc))]" aria-hidden="true"></i>orbit.studio
</span>
</header>
<div class="grid gap-3.5 px-6 pt-2" aria-hidden="true">
<div class="h-47 mb-2 rounded-2xl bg-linear-[140deg,oklch(0.9_0.03_265),oklch(0.84_0.05_300)]"></div>
<div class="h-3 w-[82%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[64%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[74%] rounded-full bg-thb01-line"></div>
<div class="h-3 w-[46%] rounded-full bg-thb01-line"></div>
</div>
<nav id="thb01-menu" aria-label="Site" class="absolute inset-0 z-2 flex flex-col justify-center gap-1.5 px-8.5 bg-[radial-gradient(120%_100%_at_100%_0%,oklch(0.3_0.08_295),var(--color-thb01-menu)_55%)] invisible [clip-path:circle(0px_at_calc(100%-46px)_46px)] [transition:clip-path_.65s_var(--ease-thb01),visibility_0s_.65s] group-data-open:visible group-data-open:[clip-path:circle(150%_at_calc(100%-46px)_46px)] group-data-open:[transition:clip-path_.65s_var(--ease-thb01),visibility_0s_0s] motion-reduce:[clip-path:none] motion-reduce:opacity-0 motion-reduce:[transition:opacity_.15s,visibility_0s_.15s] motion-reduce:group-data-open:opacity-100 motion-reduce:group-data-open:[transition:opacity_.15s]">
<a href="#work" style="--i:0" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">01</small>Work</a>
<a href="#studio" style="--i:1" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">02</small>Studio</a>
<a href="#journal" style="--i:2" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">03</small>Journal</a>
<a href="#contact" style="--i:3" class="flex items-baseline gap-3.5 py-3 px-0.5 rounded-md text-[31px] font-bold tracking-[-0.02em] text-thb01-paper no-underline opacity-0 translate-y-4.5 transition-[opacity,translate,color] duration-400 ease-thb01 hover:text-thb01-acc focus-visible:text-thb01-acc focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-4 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150"><small class="font-thb01-mono text-[11px] font-semibold text-thb01-acc tabular-nums">04</small>Contact</a>
<p style="--i:4" class="mt-6.5 font-thb01-mono text-xs text-thb01-dim opacity-0 translate-y-4.5 transition-[opacity,translate] duration-400 ease-thb01 group-data-open:opacity-100 group-data-open:translate-y-0 group-data-open:[transition-delay:calc(180ms+var(--i)*60ms)] motion-reduce:translate-y-0 motion-reduce:duration-150">hello@orbit.studio · NYC — LDN</p>
</nav>
<button type="button" aria-expanded="false" aria-controls="thb01-menu" aria-label="Open menu" class="absolute z-3 top-5.5 right-5.5 grid place-items-center w-12 h-12 rounded-full border-0 bg-thb01-ink cursor-pointer transition-[background,scale] duration-300 hover:scale-106 active:scale-94 focus-visible:outline-2 focus-visible:outline-thb01-acc focus-visible:outline-offset-3 group-data-open:bg-thb01-btnopen motion-reduce:transition-none">
<span class="relative block w-5 h-3.5" aria-hidden="true">
<i class="absolute left-0 top-0 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:translate-y-1.5 group-data-open:rotate-45 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-1.5 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[opacity,translate] duration-200 group-data-open:opacity-0 group-data-open:-translate-x-1.5 motion-reduce:transition-none"></i>
<i class="absolute left-0 top-3 w-5 h-0.5 rounded-sm bg-thb01-bg transition-[translate,rotate] duration-300 group-data-open:-translate-y-1.5 group-data-open:-rotate-45 motion-reduce:transition-none"></i>
</span>
</button>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb01-bg: #f7f7fa;
--color-thb01-bg: oklch(0.97 0.005 250);
--color-thb01-ink: #2c2f3d;
--color-thb01-ink: oklch(0.22 0.02 260);
--color-thb01-edge: #dfe0e6;
--color-thb01-edge: oklch(0.88 0.01 260);
--color-thb01-line: #e4e4ea;
--color-thb01-line: oklch(0.9 0.008 260);
--color-thb01-menu: #2f2549;
--color-thb01-menu: oklch(0.23 0.06 285);
--color-thb01-btnopen: #453a63;
--color-thb01-btnopen: oklch(0.32 0.07 295);
--color-thb01-paper: #f6f5f0;
--color-thb01-paper: oklch(0.96 0.01 90);
--color-thb01-dim: #a49ab5;
--color-thb01-dim: oklch(0.68 0.03 290);
--color-thb01-acc: #e5b45c;
--color-thb01-acc: oklch(0.8 0.16 85);
--font-thb01-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb01-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb01: cubic-bezier(0.65, 0, 0.35, 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-01 {
width: 100%;
min-height: 100svh;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.thb-01 > .group').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
var btn = stage.querySelector('button[aria-controls="thb01-menu"]');
function set(open) {
stage.toggleAttribute('data-open', open);
btn.setAttribute('aria-expanded', String(open));
btn.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
}
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
Both circles live on the panel. The CSS version writes the closed circle in one rule and the open circle in a [data-open] rule several screens away. In utilities the element holds both:
<nav class="absolute inset-0 invisible
[clip-path:circle(0px_at_calc(100%-46px)_46px)]
group-data-open:visible
group-data-open:[clip-path:circle(150%_at_calc(100%-46px)_46px)]">Move the anchor and you edit one element, not two rules — which matters, because a mismatched pair is the single most common bug in this pattern.
Why 150%. clip-path percentages resolve against a diagonal measure of the reference box, so 150% guarantees the circle swallows the farthest corner at any aspect ratio with no JS measuring.
Visibility rides along, late. A closed panel must be unfocusable, so invisible is on it — but flipped instantly it would pop the links away before the circle finishes collapsing. The arbitrary transition shorthand gives visibility a 650ms delay closing and none opening. This is the one place the shorthand beats Tailwind's transition-* scale, which cannot express per-property delays.
The script writes state; the markup writes style. Twelve lines flip data-open on the stage and keep aria-expanded on the button honest. Nothing in the script touches a class or a style, so restyling the open state never means reopening the JS.
Make it yours
- Anchor point: edit the two
calc(100%-46px)_46pxpairs on the panel —50%_100%blooms from a bottom-centre dock button. - Wavefront speed:
--ease-thb01and the.65sin the two arbitrary transitions. A springier feel:cubic-bezier(.3,1.36,.4,1)— clip-path tolerates overshoot because the circle simply grows past 100%. - Stagger tempo: the
60msmultiplier inside[transition-delay:calc(180ms+var(--i)*60ms)]; drop it to 0 and the links arrive with the circle. - Recolour through
--color-thb01-menuand--color-thb01-accin@theme— the panel gradient, the numerals and every focus ring read the same two tokens. - Promote to production by swapping the stage's
relativeforfixed inset-0and deletingh-135; the pattern is viewport-ready as-is.
Gotchas — read before shipping
- Arbitrary values cannot contain spaces.
[clip-path:circle(0px_at_calc(100%-46px)_46px)]must use the underscore escape, andcalc(100%-46px)must be typed closed-up. - Keep the button OUTSIDE the clipped panel — a sibling with a higher
z-. Inside, it gets clipped away on close and focus falls nowhere. - Transition
clip-path, never the panel'sw-/h-. The clip runs on the compositor; animating size repaints layout every frame and wrecks INP. invisibleis load-bearing, not decoration. Withopacity-0alone a keyboard user tabs into a menu they cannot see — a WCAG 2.4.7 failure.- The class string must be statically visible to the compiler. A clip-path assembled at runtime from a template variable produces no CSS at all — keep varying values in a custom property.
- The browser CDN build compiles in the page and is for prototyping only. Ship the CLI or a plugin build.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Animatable basic-shape clip-path has been Baseline since 2021, so the reveal itself runs far back; the floor quoted here is Tailwind v4's own generated sheet (cascade layers, @property, color-mix()).