22 / 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
Pure Tailwind Multi-Level Accordion Hamburger Dropdown Menu
Nested navigation with zero JavaScript and zero fake semantics: every level is a native <details>/<summary>, so keyboard support and screen-reader disclosure announcements come free. Tailwind's open: and group-open: variants read the element's own state, the name attribute makes the top level exclusive, and native toggling stays instant — the ::details-content animation is documented but deliberately not shipped.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="thb-22 w-full min-h-svh bg-thb22-bg font-thb22-sans text-thb22-ink px-5 py-9" aria-label="Multi-level accordion menu demo">
<div class="min-h-120 flex flex-col items-center justify-center gap-3.5 p-6.5 rounded-[18px] border border-thb22-edge bg-thb22-bg">
<aside aria-label="Menu" class="w-[min(340px,100%)] overflow-hidden rounded-[18px] border border-thb22-edge bg-thb22-panel shadow-[0_22px_48px_-30px_oklch(0.3_0.05_145/0.55)]">
<header class="flex items-center justify-between px-4.5 pt-4 pb-3 border-b border-thb22-edge">
<b class="text-base font-bold tracking-[-0.01em]">Browse</b>
<span class="relative block w-4.5 h-3 opacity-50" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
</span>
</header>
<nav aria-label="Categories" class="grid px-2.5 pt-2 pb-3">
<details name="thb22-top" open class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Shop
<b class="ml-auto px-2 py-0.5 rounded-full bg-thb22-badge text-[10.5px] font-bold text-thb22-mut tabular-nums">312</b>
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#new" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">New arrivals</a></li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Clothing
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#knitwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Knitwear</a></li>
<li><a href="#outerwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Outerwear</a></li>
<li><a href="#denim" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Denim</a></li>
</ul>
</details>
</li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Objects
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#ceramics" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Ceramics</a></li>
<li><a href="#lighting" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Lighting</a></li>
</ul>
</details>
</li>
<li><a href="#archive-sale" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Archive sale</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Stories
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#studio-visits" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Studio visits</a></li>
<li><a href="#process" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Process notes</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Support
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#shipping" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Shipping & returns</a></li>
<li><a href="#care" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Care guides</a></li>
<li><a href="#contact" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Contact</a></li>
</ul>
</details>
<a href="#account" class="flex items-center min-h-10.5 mt-1.5 pt-1 px-2.5 border-t border-thb22-edge text-[13.5px] font-bold text-thb22-ink no-underline transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Account</a>
</nav>
</aside>
<p class="text-center text-xs text-thb22-mut text-pretty" aria-hidden="true">native <code class="font-thb22-mono text-[11px] px-1.5 py-0.5 rounded bg-thb22-badge"><details name></code> — top level is exclusive, keyboard & screen-reader support built in, 0 JS</p>
</div>
</section><section class="thb-22 w-full min-h-svh bg-thb22-bg font-thb22-sans text-thb22-ink px-5 py-9" aria-label="Multi-level accordion menu demo">
<div class="min-h-120 flex flex-col items-center justify-center gap-3.5 p-6.5 rounded-[18px] border border-thb22-edge bg-thb22-bg">
<aside aria-label="Menu" class="w-[min(340px,100%)] overflow-hidden rounded-[18px] border border-thb22-edge bg-thb22-panel shadow-[0_22px_48px_-30px_oklch(0.3_0.05_145/0.55)]">
<header class="flex items-center justify-between px-4.5 pt-4 pb-3 border-b border-thb22-edge">
<b class="text-base font-bold tracking-[-0.01em]">Browse</b>
<span class="relative block w-4.5 h-3 opacity-50" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
</span>
</header>
<nav aria-label="Categories" class="grid px-2.5 pt-2 pb-3">
<details name="thb22-top" open class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Shop
<b class="ml-auto px-2 py-0.5 rounded-full bg-thb22-badge text-[10.5px] font-bold text-thb22-mut tabular-nums">312</b>
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#new" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">New arrivals</a></li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Clothing
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#knitwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Knitwear</a></li>
<li><a href="#outerwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Outerwear</a></li>
<li><a href="#denim" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Denim</a></li>
</ul>
</details>
</li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Objects
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#ceramics" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Ceramics</a></li>
<li><a href="#lighting" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Lighting</a></li>
</ul>
</details>
</li>
<li><a href="#archive-sale" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Archive sale</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Stories
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#studio-visits" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Studio visits</a></li>
<li><a href="#process" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Process notes</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Support
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#shipping" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Shipping & returns</a></li>
<li><a href="#care" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Care guides</a></li>
<li><a href="#contact" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Contact</a></li>
</ul>
</details>
<a href="#account" class="flex items-center min-h-10.5 mt-1.5 pt-1 px-2.5 border-t border-thb22-edge text-[13.5px] font-bold text-thb22-ink no-underline transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Account</a>
</nav>
</aside>
<p class="text-center text-xs text-thb22-mut text-pretty" aria-hidden="true">native <code class="font-thb22-mono text-[11px] px-1.5 py-0.5 rounded bg-thb22-badge"><details name></code> — top level is exclusive, keyboard & screen-reader support built in, 0 JS</p>
</div>
</section>@import "tailwindcss";
@theme {
--color-thb22-bg: #f6f8f4;
--color-thb22-bg: oklch(0.97 0.006 130);
--color-thb22-panel: #ffffff;
--color-thb22-panel: oklch(1 0 0);
--color-thb22-hover: #f0f4ee;
--color-thb22-hover: oklch(0.96 0.01 135);
--color-thb22-badge: #e7ece4;
--color-thb22-badge: oklch(0.94 0.01 135);
--color-thb22-edge: #dde3d9;
--color-thb22-edge: oklch(0.89 0.012 130);
--color-thb22-ink: #313a30;
--color-thb22-ink: oklch(0.24 0.02 140);
--color-thb22-mut: #6e766c;
--color-thb22-mut: oklch(0.5 0.018 140);
--color-thb22-acc: #4f8a5c;
--color-thb22-acc: oklch(0.55 0.14 150);
--font-thb22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb22-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb22: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* The ::details-content expansion animation is deliberately NOT shipped, and the recipe lives in
the "How it works" notes rather than in commented-out CSS here. Engines differ on whether that
slot reserves layout while its block-size animates; where it does not, an expanding submenu
paints over its siblings — worse than no animation. Native toggling is instant and correct. */
/* 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-22 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb22-bg: #f6f8f4;
--color-thb22-bg: oklch(0.97 0.006 130);
--color-thb22-panel: #ffffff;
--color-thb22-panel: oklch(1 0 0);
--color-thb22-hover: #f0f4ee;
--color-thb22-hover: oklch(0.96 0.01 135);
--color-thb22-badge: #e7ece4;
--color-thb22-badge: oklch(0.94 0.01 135);
--color-thb22-edge: #dde3d9;
--color-thb22-edge: oklch(0.89 0.012 130);
--color-thb22-ink: #313a30;
--color-thb22-ink: oklch(0.24 0.02 140);
--color-thb22-mut: #6e766c;
--color-thb22-mut: oklch(0.5 0.018 140);
--color-thb22-acc: #4f8a5c;
--color-thb22-acc: oklch(0.55 0.14 150);
--font-thb22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb22-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb22: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* The ::details-content expansion animation is deliberately NOT shipped, and the recipe lives in
the "How it works" notes rather than in commented-out CSS here. Engines differ on whether that
slot reserves layout while its block-size animates; where it does not, an expanding submenu
paints over its siblings — worse than no animation. Native toggling is instant and correct. */
/* 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-22 {
width: 100%;
min-height: 100svh;
}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-thb22-bg: #f6f8f4;
--color-thb22-bg: oklch(0.97 0.006 130);
--color-thb22-panel: #ffffff;
--color-thb22-panel: oklch(1 0 0);
--color-thb22-hover: #f0f4ee;
--color-thb22-hover: oklch(0.96 0.01 135);
--color-thb22-badge: #e7ece4;
--color-thb22-badge: oklch(0.94 0.01 135);
--color-thb22-edge: #dde3d9;
--color-thb22-edge: oklch(0.89 0.012 130);
--color-thb22-ink: #313a30;
--color-thb22-ink: oklch(0.24 0.02 140);
--color-thb22-mut: #6e766c;
--color-thb22-mut: oklch(0.5 0.018 140);
--color-thb22-acc: #4f8a5c;
--color-thb22-acc: oklch(0.55 0.14 150);
--font-thb22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb22-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb22: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* The ::details-content expansion animation is deliberately NOT shipped, and the recipe lives in
the "How it works" notes rather than in commented-out CSS here. Engines differ on whether that
slot reserves layout while its block-size animates; where it does not, an expanding submenu
paints over its siblings — worse than no animation. Native toggling is instant and correct. */
/* 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-22 {
width: 100%;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-thb22-bg: #f6f8f4;
--color-thb22-bg: oklch(0.97 0.006 130);
--color-thb22-panel: #ffffff;
--color-thb22-panel: oklch(1 0 0);
--color-thb22-hover: #f0f4ee;
--color-thb22-hover: oklch(0.96 0.01 135);
--color-thb22-badge: #e7ece4;
--color-thb22-badge: oklch(0.94 0.01 135);
--color-thb22-edge: #dde3d9;
--color-thb22-edge: oklch(0.89 0.012 130);
--color-thb22-ink: #313a30;
--color-thb22-ink: oklch(0.24 0.02 140);
--color-thb22-mut: #6e766c;
--color-thb22-mut: oklch(0.5 0.018 140);
--color-thb22-acc: #4f8a5c;
--color-thb22-acc: oklch(0.55 0.14 150);
--font-thb22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb22-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb22: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* The ::details-content expansion animation is deliberately NOT shipped, and the recipe lives in
the "How it works" notes rather than in commented-out CSS here. Engines differ on whether that
slot reserves layout while its block-size animates; where it does not, an expanding submenu
paints over its siblings — worse than no animation. Native toggling is instant and correct. */
/* 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-22 {
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.
- This is the collection's clearest example of a variant that looks right and is wrong:
group-open:on a summary-scoped group never matches ([open]is on the<details>), and hoisting the group to the<details>leaks through nesting. The port keeps the original selector shape as a direct-child arbitrary variant instead, and the.d2blocks still disappear. open:is equally a trap here — it styles the element that HAS[open], so it works on a<details>and does nothing on a<summary>. The label uses[details[open]>&]:for that reason.- Marker hiding needed three declarations and still does:
list-none marker:hidden [&::-webkit-details-marker]:hidden. Utilities make it verbose but keep the Safari workaround attached to the element that needs it. - The indent guideline (
ml-4 pl-3.5 border-l-[1.5px]) is now identical on every nested list, so depth costs a copy rather than a new class name. - The
::details-contentanimation stays in CSS — and stays switched OFF. It is the one enhancement in the collection that failed its own smoke test: in an engine that does not reserve layout for the animating slot, the submenu overlapped its siblings, so the demo ships the native instant toggle and keeps the recipe as a comment. - Zero JavaScript, and the
nameattribute does what a JS accordion controller used to: exclusivity is declarative.
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: Pure Tailwind Multi-Level Accordion Hamburger Dropdown Menu
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/pure-tailwind-multi-level-accordion-hamburger-dropdown-menu/
Nested navigation with zero JavaScript and zero fake semantics: every level is a native <details>/<summary>, so keyboard support and screen-reader disclosure announcements come free. Tailwind's open: and group-open: variants read the element's own state, the name attribute makes the top level exclusive, and native toggling stays instant — the ::details-content animation is documented but deliberately not shipped.
## HTML
```html
<section class="thb-22 w-full min-h-svh bg-thb22-bg font-thb22-sans text-thb22-ink px-5 py-9" aria-label="Multi-level accordion menu demo">
<div class="min-h-120 flex flex-col items-center justify-center gap-3.5 p-6.5 rounded-[18px] border border-thb22-edge bg-thb22-bg">
<aside aria-label="Menu" class="w-[min(340px,100%)] overflow-hidden rounded-[18px] border border-thb22-edge bg-thb22-panel shadow-[0_22px_48px_-30px_oklch(0.3_0.05_145/0.55)]">
<header class="flex items-center justify-between px-4.5 pt-4 pb-3 border-b border-thb22-edge">
<b class="text-base font-bold tracking-[-0.01em]">Browse</b>
<span class="relative block w-4.5 h-3 opacity-50" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
</span>
</header>
<nav aria-label="Categories" class="grid px-2.5 pt-2 pb-3">
<details name="thb22-top" open class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Shop
<b class="ml-auto px-2 py-0.5 rounded-full bg-thb22-badge text-[10.5px] font-bold text-thb22-mut tabular-nums">312</b>
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#new" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">New arrivals</a></li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Clothing
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#knitwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Knitwear</a></li>
<li><a href="#outerwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Outerwear</a></li>
<li><a href="#denim" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Denim</a></li>
</ul>
</details>
</li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Objects
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#ceramics" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Ceramics</a></li>
<li><a href="#lighting" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Lighting</a></li>
</ul>
</details>
</li>
<li><a href="#archive-sale" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Archive sale</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Stories
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#studio-visits" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Studio visits</a></li>
<li><a href="#process" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Process notes</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Support
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#shipping" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Shipping & returns</a></li>
<li><a href="#care" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Care guides</a></li>
<li><a href="#contact" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Contact</a></li>
</ul>
</details>
<a href="#account" class="flex items-center min-h-10.5 mt-1.5 pt-1 px-2.5 border-t border-thb22-edge text-[13.5px] font-bold text-thb22-ink no-underline transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Account</a>
</nav>
</aside>
<p class="text-center text-xs text-thb22-mut text-pretty" aria-hidden="true">native <code class="font-thb22-mono text-[11px] px-1.5 py-0.5 rounded bg-thb22-badge"><details name></code> — top level is exclusive, keyboard & screen-reader support built in, 0 JS</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb22-bg: #f6f8f4;
--color-thb22-bg: oklch(0.97 0.006 130);
--color-thb22-panel: #ffffff;
--color-thb22-panel: oklch(1 0 0);
--color-thb22-hover: #f0f4ee;
--color-thb22-hover: oklch(0.96 0.01 135);
--color-thb22-badge: #e7ece4;
--color-thb22-badge: oklch(0.94 0.01 135);
--color-thb22-edge: #dde3d9;
--color-thb22-edge: oklch(0.89 0.012 130);
--color-thb22-ink: #313a30;
--color-thb22-ink: oklch(0.24 0.02 140);
--color-thb22-mut: #6e766c;
--color-thb22-mut: oklch(0.5 0.018 140);
--color-thb22-acc: #4f8a5c;
--color-thb22-acc: oklch(0.55 0.14 150);
--font-thb22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb22-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb22: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* The ::details-content expansion animation is deliberately NOT shipped, and the recipe lives in
the "How it works" notes rather than in commented-out CSS here. Engines differ on whether that
slot reserves layout while its block-size animates; where it does not, an expanding submenu
paints over its siblings — worse than no animation. Native toggling is instant and correct. */
/* 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-22 {
width: 100%;
min-height: 100svh;
}
```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: Pure Tailwind Multi-Level Accordion Hamburger Dropdown Menu
Source: https://codefronts.com/navigation/tailwind-hamburger-menus/pure-tailwind-multi-level-accordion-hamburger-dropdown-menu/
Nested navigation with zero JavaScript and zero fake semantics: every level is a native <details>/<summary>, so keyboard support and screen-reader disclosure announcements come free. Tailwind's open: and group-open: variants read the element's own state, the name attribute makes the top level exclusive, and native toggling stays instant — the ::details-content animation is documented but deliberately not shipped.
## HTML
```html
<section class="thb-22 w-full min-h-svh bg-thb22-bg font-thb22-sans text-thb22-ink px-5 py-9" aria-label="Multi-level accordion menu demo">
<div class="min-h-120 flex flex-col items-center justify-center gap-3.5 p-6.5 rounded-[18px] border border-thb22-edge bg-thb22-bg">
<aside aria-label="Menu" class="w-[min(340px,100%)] overflow-hidden rounded-[18px] border border-thb22-edge bg-thb22-panel shadow-[0_22px_48px_-30px_oklch(0.3_0.05_145/0.55)]">
<header class="flex items-center justify-between px-4.5 pt-4 pb-3 border-b border-thb22-edge">
<b class="text-base font-bold tracking-[-0.01em]">Browse</b>
<span class="relative block w-4.5 h-3 opacity-50" aria-hidden="true">
<i class="absolute left-0 top-0 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-[5px] w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
<i class="absolute left-0 top-2.5 w-4.5 h-0.5 rounded-sm bg-thb22-ink"></i>
</span>
</header>
<nav aria-label="Categories" class="grid px-2.5 pt-2 pb-3">
<details name="thb22-top" open class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Shop
<b class="ml-auto px-2 py-0.5 rounded-full bg-thb22-badge text-[10.5px] font-bold text-thb22-mut tabular-nums">312</b>
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#new" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">New arrivals</a></li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Clothing
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#knitwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Knitwear</a></li>
<li><a href="#outerwear" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Outerwear</a></li>
<li><a href="#denim" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Denim</a></li>
</ul>
</details>
</li>
<li>
<details class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-10.5 px-2.5 rounded-[10px] text-[13.5px] font-semibold text-thb22-mut cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] transition-[rotate] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Objects
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-1.5 border-l-[1.5px] border-thb22-edge">
<li><a href="#ceramics" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Ceramics</a></li>
<li><a href="#lighting" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Lighting</a></li>
</ul>
</details>
</li>
<li><a href="#archive-sale" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Archive sale</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Stories
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#studio-visits" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Studio visits</a></li>
<li><a href="#process" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Process notes</a></li>
</ul>
</details>
<details name="thb22-top" class="thb22-d">
<summary class="flex items-center gap-2.5 min-h-11.5 px-2.5 rounded-[10px] text-[14.5px] font-bold cursor-pointer list-none marker:hidden [&::-webkit-details-marker]:hidden transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2 [details[open]>&]:text-thb22-acc">
<svg viewBox="0 0 24 24" class="w-3.75 h-3.75 shrink-0 fill-none stroke-current stroke-[2.2] [stroke-linecap:round] [stroke-linejoin:round] text-thb22-mut transition-[rotate,color] duration-250 ease-thb22 [details[open]>summary>&]:rotate-90 [details[open]>summary>&]:text-thb22-acc motion-reduce:transition-none" aria-hidden="true"><path d="m9 5 7 7-7 7"/></svg>Support
</summary>
<ul class="list-none grid ml-4 pl-3.5 pt-0.5 pb-2 border-l-[1.5px] border-thb22-edge">
<li><a href="#shipping" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Shipping & returns</a></li>
<li><a href="#care" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Care guides</a></li>
<li><a href="#contact" class="flex items-center min-h-10.5 px-2.5 rounded-[9px] text-[13.5px] font-semibold text-thb22-mut no-underline transition-[background,color,translate] duration-150 hover:bg-thb22-hover hover:text-thb22-ink hover:translate-x-0.5 focus-visible:bg-thb22-hover focus-visible:text-thb22-ink focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Contact</a></li>
</ul>
</details>
<a href="#account" class="flex items-center min-h-10.5 mt-1.5 pt-1 px-2.5 border-t border-thb22-edge text-[13.5px] font-bold text-thb22-ink no-underline transition-[background,color] duration-150 hover:bg-thb22-hover focus-visible:bg-thb22-hover focus-visible:outline-2 focus-visible:outline-thb22-acc focus-visible:-outline-offset-2">Account</a>
</nav>
</aside>
<p class="text-center text-xs text-thb22-mut text-pretty" aria-hidden="true">native <code class="font-thb22-mono text-[11px] px-1.5 py-0.5 rounded bg-thb22-badge"><details name></code> — top level is exclusive, keyboard & screen-reader support built in, 0 JS</p>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-thb22-bg: #f6f8f4;
--color-thb22-bg: oklch(0.97 0.006 130);
--color-thb22-panel: #ffffff;
--color-thb22-panel: oklch(1 0 0);
--color-thb22-hover: #f0f4ee;
--color-thb22-hover: oklch(0.96 0.01 135);
--color-thb22-badge: #e7ece4;
--color-thb22-badge: oklch(0.94 0.01 135);
--color-thb22-edge: #dde3d9;
--color-thb22-edge: oklch(0.89 0.012 130);
--color-thb22-ink: #313a30;
--color-thb22-ink: oklch(0.24 0.02 140);
--color-thb22-mut: #6e766c;
--color-thb22-mut: oklch(0.5 0.018 140);
--color-thb22-acc: #4f8a5c;
--color-thb22-acc: oklch(0.55 0.14 150);
--font-thb22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-thb22-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-thb22: cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* The ::details-content expansion animation is deliberately NOT shipped, and the recipe lives in
the "How it works" notes rather than in commented-out CSS here. Engines differ on whether that
slot reserves layout while its block-size animates; where it does not, an expanding submenu
paints over its siblings — worse than no animation. Native toggling is instant and correct. */
/* 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-22 {
width: 100%;
min-height: 100svh;
}
```How this works
The component is the platform's own disclosure element, nested.
<details name="thb22-top"> <!-- shared name = exclusive group -->
<summary class="[details[open]>&]:text-thb22-acc …">
<svg class="[details[open]>summary>&]:rotate-90 …"></svg>Shop
</summary>
<ul class="ml-4 pl-3.5 border-l-[1.5px]">…</ul>
</details><summary> is a real button to the platform: Enter and Space toggle it, and screen readers announce “Shop, button, collapsed” with no ARIA written by you. The name attribute gives mutually exclusive top-level sections declaratively — remove it and they open independently.
Where the port is subtle. The obvious move is group on the summary plus group-open: on the chevron — and it silently fails, because [open] lands on the <details>, not the summary. Moving group up to the <details> fails differently: group-open: compiles to .group[open] &, which matches through ANY open ancestor, so a closed submenu's chevron rotates whenever its parent section is open. The honest answer is a direct-child arbitrary variant, [details[open]>summary>&]:rotate-90, which is exactly the original CSS selector written from the element's side.
Where it does not. Hiding the default marker still takes three declarations, one of them a vendor pseudo-element, and the ::details-content animation cannot be a utility — it targets an internal slot and depends on interpolate-size being set on an ancestor. Both stay in the stylesheet, and that is the right call.
Why the animation is not shipped here. ::details-content is an internal slot, and engines differ on whether it reserves layout while its block-size animates. Where it does not, an expanding submenu paints straight over the items below it — strictly worse than no animation. To try it: set interpolate-size: allow-keywords on the demo root, then give .thb22-d::details-content block-size:0; overflow:hidden with a block-size transition (plus content-visibility with allow-discrete), and block-size:auto when [open] — but test it in your own target engines first. Native toggling is instant, correct everywhere, and precisely what <details> has done for fifteen years.
Make it yours
- Exclusive versus independent top level is the
nameattribute. Delete it for multi-open; sub-levels here are independent on purpose, because users compare subcategories. - Depth is structurally unlimited; visually stop at three. Each level adds
ml-4 pl-3.5, and three of those is all a 320px drawer can afford. - Pre-open the current path by server-rendering
openon the<details>chain — the user lands seeing where they are. - To force one open at every level, add a
nameper level (name="lvl2-shop"). Grouping is per-name, so it nests cleanly. - Retheme through
--color-thb22-acc, which drives every open chevron, open label and focus ring.
Gotchas — read before shipping
- Do not put an
<a>inside a<summary>for rows that both navigate and expand — a control cannot honestly be both link and button. Split it, or make the parent a pure category as here. - Hiding the marker needs BOTH
list-noneand the::-webkit-details-markerrule, or Safari leaves a ghost gap.marker:hiddenalone is not enough. - The
nameattribute silently no-ops in engines older than 2024 — sections just open independently. Fine for navigation; if exclusivity is business-critical you need a shim. - Animating with
max-h-*re-introduces the classic timing lag AND fights thenameattribute, because the closing panel loses[open]immediately and snaps. Test any::details-contentanimation for layout reservation before shipping it: if the slot does not take space while animating, the submenu draws over the rows beneath it. - Neither
open:on a summary norgroup-open:from a summary-scoped group works:[open]belongs to the<details>. Andgroup-open:from a details-scoped group matches through every open ancestor, so nested chevrons rotate together. Use the direct-child form. interpolate-sizeis inherited. Scope it to the component root so unrelatedheight:autotransitions elsewhere on the page stay unaffected.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 120+ | 17.4+ | 130+ | 120+ |
<details>/<summary> are universal. name-exclusivity is Chrome 120, Safari 17.2 and Firefox 130; the the ::details-content animation is Chrome 131+ and rolling out elsewhere; this demo documents it but ships the native instant toggle.