10 / 22
All 22 in 22 Tailwind Dropdown Menus
- 01Tailwind Slide-Down Fade Dropdown Menu
- 02Tailwind Clip-Path Curtain Reveal Dropdown
- 03Tailwind 3D Perspective Flip Dropdown
- 04Tailwind Elastic Bounce Dropdown Menu
- 05Tailwind Glassmorphism Float Panel Dropdown
- 06Tailwind Stagger Children Reveal Dropdown
- 07Tailwind Mega Menu Grid Dropdown
- 08Tailwind Underline Nav Fade Panel Dropdown
- 09Tailwind Details Summary Native Dropdown
- 10Tailwind Checkbox Hack Mobile Nav Dropdown
- 11Tailwind Nested Multi-Level Dropdown
- 12Tailwind Icon Sidebar Flyout Dropdown
- 13Tailwind Split-Screen Mega Menu Dropdown
- 14Tailwind Segmented Pill Nav Dropdown
- 15Tailwind Color Swatch Picker Dropdown
- 16Tailwind Right-Click Context Menu Dropdown
- 17Tailwind Keyboard Accessible ARIA Dropdown
- 18Tailwind Stagger Blur Entrance Dropdown
- 19Tailwind Command Palette Search Dropdown
- 20Tailwind Autocomplete Suggestion Dropdown
- 21Tailwind Tab Panel Dropdown
- 22Tailwind Custom Animated Select Dropdown
Tailwind Checkbox Hack Mobile Nav Dropdown
The no-JS mobile nav, and the demo where peer earns its keep: a visually hidden checkbox is the state, and peer-checked: drives both the burger-to-X morph and the panel reveal from two elements away — no ~ selectors, no stylesheet.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tdd-10 w-full min-h-svh grid justify-center content-start bg-tdd10-bg font-tdd10-sans text-tdd10-ink px-5 py-10" aria-label="Checkbox hack mobile nav dropdown demo">
<div class="w-[min(440px,100%)] overflow-hidden rounded-2xl border border-tdd10-edge bg-linear-[160deg,#fff,var(--color-tdd10-bg)] shadow-[0_4px_24px_oklch(0_0_0/0.08)]">
<input type="checkbox" id="tdd10-toggle" class="peer sr-only">
<header class="relative z-10 flex items-center justify-between border-b border-tdd10-edge bg-white px-5 py-4.5">
<a href="#home" class="text-xl font-bold tracking-[-0.5px] text-tdd10-ink no-underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd10-acc">Forge</a>
<label for="tdd10-toggle" aria-label="Toggle menu" class="flex size-11 cursor-pointer flex-col items-center justify-center gap-[5px] rounded-lg p-2 transition-colors duration-150 hover:bg-tdd10-bg peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tdd10-acc">
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-[opacity,transform] duration-200 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
</label>
</header>
<nav role="navigation" aria-label="Main navigation" class="flex max-h-0 flex-col overflow-hidden bg-white opacity-0 transition-[max-height,opacity] duration-380 peer-checked:max-h-100 peer-checked:opacity-100 motion-reduce:transition-none">
<a href="#work" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Work</a>
<a href="#services" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Services</a>
<a href="#about" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">About</a>
<a href="#journal" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Journal</a>
<a href="#start" class="block px-6 py-5 text-[15px] font-semibold text-tdd10-acc no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-accdark focus-visible:pl-8 focus-visible:outline-none motion-reduce:transition-none">Start a Project</a>
</nav>
</div>
</section><section class="tdd-10 w-full min-h-svh grid justify-center content-start bg-tdd10-bg font-tdd10-sans text-tdd10-ink px-5 py-10" aria-label="Checkbox hack mobile nav dropdown demo">
<div class="w-[min(440px,100%)] overflow-hidden rounded-2xl border border-tdd10-edge bg-linear-[160deg,#fff,var(--color-tdd10-bg)] shadow-[0_4px_24px_oklch(0_0_0/0.08)]">
<input type="checkbox" id="tdd10-toggle" class="peer sr-only">
<header class="relative z-10 flex items-center justify-between border-b border-tdd10-edge bg-white px-5 py-4.5">
<a href="#home" class="text-xl font-bold tracking-[-0.5px] text-tdd10-ink no-underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd10-acc">Forge</a>
<label for="tdd10-toggle" aria-label="Toggle menu" class="flex size-11 cursor-pointer flex-col items-center justify-center gap-[5px] rounded-lg p-2 transition-colors duration-150 hover:bg-tdd10-bg peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tdd10-acc">
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-[opacity,transform] duration-200 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
</label>
</header>
<nav role="navigation" aria-label="Main navigation" class="flex max-h-0 flex-col overflow-hidden bg-white opacity-0 transition-[max-height,opacity] duration-380 peer-checked:max-h-100 peer-checked:opacity-100 motion-reduce:transition-none">
<a href="#work" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Work</a>
<a href="#services" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Services</a>
<a href="#about" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">About</a>
<a href="#journal" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Journal</a>
<a href="#start" class="block px-6 py-5 text-[15px] font-semibold text-tdd10-acc no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-accdark focus-visible:pl-8 focus-visible:outline-none motion-reduce:transition-none">Start a Project</a>
</nav>
</div>
</section>@import "tailwindcss";
@theme {
--color-tdd10-bg: #f9fafb;
--color-tdd10-bg: oklch(0.98 0.002 265);
--color-tdd10-ink: #111827;
--color-tdd10-ink: oklch(0.21 0.02 265);
--color-tdd10-edge: #f3f4f6;
--color-tdd10-edge: oklch(0.96 0.003 265);
--color-tdd10-acc: #f59e0b;
--color-tdd10-acc: oklch(0.75 0.16 70);
--color-tdd10-accdark: #d97706;
--color-tdd10-accdark: oklch(0.65 0.15 60);
--font-tdd10-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* The three burger bars are structural siblings, not indexed content, so the
nth-child morph is the one rule that reads better in CSS than as three
arbitrary variants on one label. */
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(1) {
transform: translateY(7px) rotate(45deg);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(2) {
opacity: 0;
transform: scaleX(0);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(3) {
transform: translateY(-7px) rotate(-45deg);
}
.tdd-10 {
width: 100%;
min-height: 100svh;
}
.tdd-10 ::selection {
background: var(--color-tdd10-ink);
color: #f9fafb;
}@import "tailwindcss";
@theme {
--color-tdd10-bg: #f9fafb;
--color-tdd10-bg: oklch(0.98 0.002 265);
--color-tdd10-ink: #111827;
--color-tdd10-ink: oklch(0.21 0.02 265);
--color-tdd10-edge: #f3f4f6;
--color-tdd10-edge: oklch(0.96 0.003 265);
--color-tdd10-acc: #f59e0b;
--color-tdd10-acc: oklch(0.75 0.16 70);
--color-tdd10-accdark: #d97706;
--color-tdd10-accdark: oklch(0.65 0.15 60);
--font-tdd10-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* The three burger bars are structural siblings, not indexed content, so the
nth-child morph is the one rule that reads better in CSS than as three
arbitrary variants on one label. */
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(1) {
transform: translateY(7px) rotate(45deg);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(2) {
opacity: 0;
transform: scaleX(0);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(3) {
transform: translateY(-7px) rotate(-45deg);
}
.tdd-10 {
width: 100%;
min-height: 100svh;
}
.tdd-10 ::selection {
background: var(--color-tdd10-ink);
color: #f9fafb;
}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-tdd10-bg: #f9fafb;
--color-tdd10-bg: oklch(0.98 0.002 265);
--color-tdd10-ink: #111827;
--color-tdd10-ink: oklch(0.21 0.02 265);
--color-tdd10-edge: #f3f4f6;
--color-tdd10-edge: oklch(0.96 0.003 265);
--color-tdd10-acc: #f59e0b;
--color-tdd10-acc: oklch(0.75 0.16 70);
--color-tdd10-accdark: #d97706;
--color-tdd10-accdark: oklch(0.65 0.15 60);
--font-tdd10-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* The three burger bars are structural siblings, not indexed content, so the
nth-child morph is the one rule that reads better in CSS than as three
arbitrary variants on one label. */
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(1) {
transform: translateY(7px) rotate(45deg);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(2) {
opacity: 0;
transform: scaleX(0);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(3) {
transform: translateY(-7px) rotate(-45deg);
}
.tdd-10 {
width: 100%;
min-height: 100svh;
}
.tdd-10 ::selection {
background: var(--color-tdd10-ink);
color: #f9fafb;
}@import "tailwindcss";
@theme {
--color-tdd10-bg: #f9fafb;
--color-tdd10-bg: oklch(0.98 0.002 265);
--color-tdd10-ink: #111827;
--color-tdd10-ink: oklch(0.21 0.02 265);
--color-tdd10-edge: #f3f4f6;
--color-tdd10-edge: oklch(0.96 0.003 265);
--color-tdd10-acc: #f59e0b;
--color-tdd10-acc: oklch(0.75 0.16 70);
--color-tdd10-accdark: #d97706;
--color-tdd10-accdark: oklch(0.65 0.15 60);
--font-tdd10-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* The three burger bars are structural siblings, not indexed content, so the
nth-child morph is the one rule that reads better in CSS than as three
arbitrary variants on one label. */
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(1) {
transform: translateY(7px) rotate(45deg);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(2) {
opacity: 0;
transform: scaleX(0);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(3) {
transform: translateY(-7px) rotate(-45deg);
}
.tdd-10 {
width: 100%;
min-height: 100svh;
}
.tdd-10 ::selection {
background: var(--color-tdd10-ink);
color: #f9fafb;
}<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&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&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
peer-checked:replaces every#id:checked ~ .menuselector for the panel — the state is read on the element that responds to it.- The burger morph is the collection's honest exception: three
peer-checked:[&>span:nth-child(n)]:variants on one label is less readable than three CSS lines, so the CSS stays. Porting is a judgement, not a rule. sr-onlyinstead ofhiddenis the accessibility decision that makes this pattern defensible at all.peer-focus-visible:on the label transfers the input's focus ring to the visible control — the CSS version has no keyboard affordance whatsoever.
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 Checkbox Hack Mobile Nav Dropdown
Source: https://codefronts.com/navigation/tailwind-dropdown-menus/tailwind-checkbox-hack-mobile-nav-dropdown/
The no-JS mobile nav, and the demo where peer earns its keep: a visually hidden checkbox is the state, and peer-checked: drives both the burger-to-X morph and the panel reveal from two elements away — no ~ selectors, no stylesheet.
## HTML
```html
<section class="tdd-10 w-full min-h-svh grid justify-center content-start bg-tdd10-bg font-tdd10-sans text-tdd10-ink px-5 py-10" aria-label="Checkbox hack mobile nav dropdown demo">
<div class="w-[min(440px,100%)] overflow-hidden rounded-2xl border border-tdd10-edge bg-linear-[160deg,#fff,var(--color-tdd10-bg)] shadow-[0_4px_24px_oklch(0_0_0/0.08)]">
<input type="checkbox" id="tdd10-toggle" class="peer sr-only">
<header class="relative z-10 flex items-center justify-between border-b border-tdd10-edge bg-white px-5 py-4.5">
<a href="#home" class="text-xl font-bold tracking-[-0.5px] text-tdd10-ink no-underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd10-acc">Forge</a>
<label for="tdd10-toggle" aria-label="Toggle menu" class="flex size-11 cursor-pointer flex-col items-center justify-center gap-[5px] rounded-lg p-2 transition-colors duration-150 hover:bg-tdd10-bg peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tdd10-acc">
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-[opacity,transform] duration-200 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
</label>
</header>
<nav role="navigation" aria-label="Main navigation" class="flex max-h-0 flex-col overflow-hidden bg-white opacity-0 transition-[max-height,opacity] duration-380 peer-checked:max-h-100 peer-checked:opacity-100 motion-reduce:transition-none">
<a href="#work" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Work</a>
<a href="#services" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Services</a>
<a href="#about" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">About</a>
<a href="#journal" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Journal</a>
<a href="#start" class="block px-6 py-5 text-[15px] font-semibold text-tdd10-acc no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-accdark focus-visible:pl-8 focus-visible:outline-none motion-reduce:transition-none">Start a Project</a>
</nav>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdd10-bg: #f9fafb;
--color-tdd10-bg: oklch(0.98 0.002 265);
--color-tdd10-ink: #111827;
--color-tdd10-ink: oklch(0.21 0.02 265);
--color-tdd10-edge: #f3f4f6;
--color-tdd10-edge: oklch(0.96 0.003 265);
--color-tdd10-acc: #f59e0b;
--color-tdd10-acc: oklch(0.75 0.16 70);
--color-tdd10-accdark: #d97706;
--color-tdd10-accdark: oklch(0.65 0.15 60);
--font-tdd10-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* The three burger bars are structural siblings, not indexed content, so the
nth-child morph is the one rule that reads better in CSS than as three
arbitrary variants on one label. */
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(1) {
transform: translateY(7px) rotate(45deg);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(2) {
opacity: 0;
transform: scaleX(0);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(3) {
transform: translateY(-7px) rotate(-45deg);
}
.tdd-10 {
width: 100%;
min-height: 100svh;
}
.tdd-10 ::selection {
background: var(--color-tdd10-ink);
color: #f9fafb;
}
```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 Checkbox Hack Mobile Nav Dropdown
Source: https://codefronts.com/navigation/tailwind-dropdown-menus/tailwind-checkbox-hack-mobile-nav-dropdown/
The no-JS mobile nav, and the demo where peer earns its keep: a visually hidden checkbox is the state, and peer-checked: drives both the burger-to-X morph and the panel reveal from two elements away — no ~ selectors, no stylesheet.
## HTML
```html
<section class="tdd-10 w-full min-h-svh grid justify-center content-start bg-tdd10-bg font-tdd10-sans text-tdd10-ink px-5 py-10" aria-label="Checkbox hack mobile nav dropdown demo">
<div class="w-[min(440px,100%)] overflow-hidden rounded-2xl border border-tdd10-edge bg-linear-[160deg,#fff,var(--color-tdd10-bg)] shadow-[0_4px_24px_oklch(0_0_0/0.08)]">
<input type="checkbox" id="tdd10-toggle" class="peer sr-only">
<header class="relative z-10 flex items-center justify-between border-b border-tdd10-edge bg-white px-5 py-4.5">
<a href="#home" class="text-xl font-bold tracking-[-0.5px] text-tdd10-ink no-underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdd10-acc">Forge</a>
<label for="tdd10-toggle" aria-label="Toggle menu" class="flex size-11 cursor-pointer flex-col items-center justify-center gap-[5px] rounded-lg p-2 transition-colors duration-150 hover:bg-tdd10-bg peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tdd10-acc">
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-[opacity,transform] duration-200 motion-reduce:transition-none"></span>
<span class="block h-0.5 w-5 origin-center rounded-sm bg-tdd10-ink transition-transform duration-300 motion-reduce:transition-none"></span>
</label>
</header>
<nav role="navigation" aria-label="Main navigation" class="flex max-h-0 flex-col overflow-hidden bg-white opacity-0 transition-[max-height,opacity] duration-380 peer-checked:max-h-100 peer-checked:opacity-100 motion-reduce:transition-none">
<a href="#work" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Work</a>
<a href="#services" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Services</a>
<a href="#about" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">About</a>
<a href="#journal" class="block border-b border-tdd10-edge px-6 py-4.5 text-[22px] font-bold tracking-[-0.5px] text-tdd10-ink no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-acc focus-visible:pl-8 focus-visible:text-tdd10-acc focus-visible:outline-none motion-reduce:transition-none">Journal</a>
<a href="#start" class="block px-6 py-5 text-[15px] font-semibold text-tdd10-acc no-underline transition-[color,padding] duration-200 hover:pl-8 hover:text-tdd10-accdark focus-visible:pl-8 focus-visible:outline-none motion-reduce:transition-none">Start a Project</a>
</nav>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdd10-bg: #f9fafb;
--color-tdd10-bg: oklch(0.98 0.002 265);
--color-tdd10-ink: #111827;
--color-tdd10-ink: oklch(0.21 0.02 265);
--color-tdd10-edge: #f3f4f6;
--color-tdd10-edge: oklch(0.96 0.003 265);
--color-tdd10-acc: #f59e0b;
--color-tdd10-acc: oklch(0.75 0.16 70);
--color-tdd10-accdark: #d97706;
--color-tdd10-accdark: oklch(0.65 0.15 60);
--font-tdd10-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* The three burger bars are structural siblings, not indexed content, so the
nth-child morph is the one rule that reads better in CSS than as three
arbitrary variants on one label. */
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(1) {
transform: translateY(7px) rotate(45deg);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(2) {
opacity: 0;
transform: scaleX(0);
}
.tdd-10 #tdd10-toggle:checked ~ header label span:nth-child(3) {
transform: translateY(-7px) rotate(-45deg);
}
.tdd-10 {
width: 100%;
min-height: 100svh;
}
.tdd-10 ::selection {
background: var(--color-tdd10-ink);
color: #f9fafb;
}
```How this works
The input is the state and the label is the button. Because the checkbox is a real focusable control, the menu is keyboard operable with no script — Tab to the burger, Space to open.
<input type="checkbox" id="tdd10-t" class="peer sr-only">
<header><label for="tdd10-t" …>…</label></header>
<nav class="max-h-0 opacity-0 peer-checked:max-h-100 peer-checked:opacity-100">peer-checked: reaches any later sibling, and an arbitrary child variant reaches inside it — which is how the three burger bars morph while living two levels below the input.
sr-only, never hidden. A display:none checkbox is not focusable, and the entire keyboard story collapses. The utility exists precisely for this.
The X is three transforms. Top bar down and +45°, middle bar to scale-x-0 opacity-0, bottom bar up and −45°, all on the same 300ms.
Make it yours
- Drawer instead of dropdown: swap the
max-h-*pair for-translate-x-full peer-checked:translate-x-0. - Backdrop: add a sibling
divwithopacity-0 peer-checked:opacity-100and alabeloverlay to close on outside tap. - Bar weight: the three
<span>s areh-0.5 w-5; scale both together. - Link scale: the panel links are deliberately large (
text-[22px]) — this is a touch nav, not a desktop menu.
Gotchas — read before shipping
peeronly reaches LATER siblings. The input must precede everything it controls in source order.hiddenordisplay:noneon the input kills focusability — alwayssr-only.- Screen readers do not announce a checkbox as a menu button; add
aria-labelon the label and considerrole="button"semantics if this is your primary nav. - Multiple checkbox menus on one page need unique ids, or one label toggles the wrong menu.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
The checkbox/label pattern works everywhere; peer-* compiles to plain sibling selectors.