SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/tailwind-hamburger-menus

6 Tailwind Hamburger Menus

3 Tailwind3 with JSPublished 2026-10-04Free · no sign-up

Six hamburger icons and mobile menus in Tailwind: an icon that morphs into a cross, a button with a visible Menu label, a slide-out panel, a full-screen overlay with staggered links, kebab and meatball icons and a small dropdown menu.

01. Tailwind Hamburger to Cross

TailwindAnimation

A three-line menu icon that turns into a cross, styled entirely with Tailwind's aria-expanded: variants via group-aria-expanded:. The script only flips aria-expanded, so the animation always matches the announced state.

View code
<button aria-expanded="false" aria-label="Menu" class="group grid h-12 w-12 place-content-center gap-1.5 rounded-xl border border-slate-700 bg-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-400" onclick="this.setAttribute('aria-expanded', this.getAttribute('aria-expanded') !== 'true')">
  <span class="block h-0.5 w-6 rounded bg-white transition-transform group-aria-expanded:translate-y-2 group-aria-expanded:rotate-45 motion-reduce:transition-none"></span>
  <span class="block h-0.5 w-6 rounded bg-white transition-opacity group-aria-expanded:opacity-0"></span>
  <span class="block h-0.5 w-6 rounded bg-white transition-transform group-aria-expanded:-translate-y-2 group-aria-expanded:-rotate-45 motion-reduce:transition-none"></span>
</button>

02. Tailwind Menu Button with Label

TailwindUsability

A pill button that shows both the icon and the word Menu, switching to Close when open. Visible text helps people who do not recognise the three-line icon and also serves as the accessible name, so no aria-label is needed.

View code
<button aria-expanded="false" class="group inline-flex items-center gap-2.5 rounded-full border-2 border-slate-900 px-4 py-2 text-sm font-bold uppercase tracking-wider text-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600" onclick="var o=this.getAttribute('aria-expanded')!=='true';this.setAttribute('aria-expanded',o);this.querySelector('.tx').textContent=o?'Close':'Menu'">
  <span aria-hidden="true" class="grid w-4 gap-1"><i class="block h-0.5 bg-current transition group-aria-expanded:translate-y-1.5 group-aria-expanded:rotate-45"></i><i class="block h-0.5 bg-current transition group-aria-expanded:opacity-0"></i><i class="block h-0.5 bg-current transition group-aria-expanded:-translate-y-1.5 group-aria-expanded:-rotate-45"></i></span>
  <span class="tx">Menu</span>
</button>

03. Tailwind Slide-Out Mobile Menu

TailwindMobile

A phone-sized header with a hamburger that slides a panel in from the left. The panel uses translate utilities toggled by a data-open attribute and the data-[open]: variant, and Escape closes it and returns focus to the button.

View code
<div class="relative h-80 w-72 overflow-hidden rounded-3xl bg-slate-50 ring-8 ring-slate-900" id="twso">
  <header class="flex items-center justify-between border-b border-slate-200 bg-white px-4 py-3"><b class="text-slate-900">Fernhill</b>
    <button aria-expanded="false" aria-controls="twso-p" aria-label="Menu" class="grid h-10 w-10 place-content-center gap-1 rounded-lg bg-slate-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-600"><i class="block h-0.5 w-5 bg-slate-900"></i><i class="block h-0.5 w-5 bg-slate-900"></i><i class="block h-0.5 w-5 bg-slate-900"></i></button>
  </header>
  <nav id="twso-p" aria-label="Main" class="invisible absolute bottom-0 left-0 top-[65px] w-4/5 -translate-x-full bg-slate-900 transition-transform data-[open]:visible data-[open]:translate-x-0 motion-reduce:transition-none">
    <ul class="py-3"><li><a href="#" class="block px-6 py-3 font-semibold text-white hover:bg-slate-800 focus:bg-slate-800 focus:outline-none">Shop</a></li><li><a href="#" class="block px-6 py-3 font-semibold text-white hover:bg-slate-800 focus:bg-slate-800 focus:outline-none">Workshops</a></li><li><a href="#" class="block px-6 py-3 font-semibold text-white hover:bg-slate-800 focus:bg-slate-800 focus:outline-none">Contact</a></li></ul>
  </nav>
</div>
const sb = document.querySelector('#twso button'), sp = document.getElementById('twso-p');
function set(o) { sb.setAttribute('aria-expanded', String(o)); sp.toggleAttribute('data-open', o); if (o) sp.querySelector('a').focus(); }
sb.addEventListener('click', () => set(!sp.hasAttribute('data-open')));
document.addEventListener('keydown', e => { if (e.key === 'Escape' && sp.hasAttribute('data-open')) { set(false); sb.focus(); } });

04. Tailwind Full-Screen Menu

TailwindOverlay

A full-screen overlay menu with very large links that fade and rise in one after another. The stagger uses Tailwind's delay utilities on each link, and the overlay is invisible to keyboard and screen readers until it opens.

View code
<div class="relative h-80 w-full max-w-md overflow-hidden rounded-2xl bg-slate-950" id="twfs">
  <button aria-expanded="false" aria-controls="twfs-m" class="absolute right-4 top-4 z-10 rounded-full border border-white px-4 py-1.5 text-sm font-bold text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-pink-400">Menu</button>
  <nav id="twfs-m" aria-label="Main" class="group invisible absolute inset-0 grid content-center gap-1 bg-gradient-to-br from-indigo-950 to-slate-950 px-8 opacity-0 transition data-[open]:visible data-[open]:opacity-100 motion-reduce:transition-none">
    <a href="#" class="translate-y-3 text-4xl font-extrabold text-white opacity-0 transition duration-500 hover:text-pink-400 focus:text-pink-400 focus:outline-none group-data-[open]:translate-y-0 group-data-[open]:opacity-100">Work</a>
    <a href="#" class="translate-y-3 text-4xl font-extrabold text-white opacity-0 transition delay-75 duration-500 hover:text-pink-400 focus:text-pink-400 focus:outline-none group-data-[open]:translate-y-0 group-data-[open]:opacity-100">Studio</a>
    <a href="#" class="translate-y-3 text-4xl font-extrabold text-white opacity-0 transition delay-150 duration-500 hover:text-pink-400 focus:text-pink-400 focus:outline-none group-data-[open]:translate-y-0 group-data-[open]:opacity-100">Journal</a>
    <a href="#" class="translate-y-3 text-4xl font-extrabold text-white opacity-0 transition delay-200 duration-500 hover:text-pink-400 focus:text-pink-400 focus:outline-none group-data-[open]:translate-y-0 group-data-[open]:opacity-100">Contact</a>
  </nav>
</div>
const ob = document.querySelector('#twfs button'), om = document.getElementById('twfs-m');
ob.addEventListener('click', () => { const o = !om.hasAttribute('data-open'); om.toggleAttribute('data-open', o); ob.setAttribute('aria-expanded', String(o)); ob.textContent = o ? 'Close' : 'Menu'; });

05. Tailwind Kebab and Meatball Icons

TailwindIcon

Vertical and horizontal three-dot overflow icons drawn with a single dot and an arbitrary box-shadow value that copies it twice. Each is a button with an accessible name, so they work as triggers for any menu.

View code
<div class="flex gap-5">
  <button aria-label="More options" aria-haspopup="menu" class="grid h-11 w-11 place-items-center rounded-xl border border-slate-300 bg-white hover:bg-slate-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"><span class="h-1 w-1 rounded-full bg-slate-900 shadow-[0_-7px_0_#0f172a,0_7px_0_#0f172a]"></span></button>
  <button aria-label="More actions" aria-haspopup="menu" class="grid h-11 w-11 place-items-center rounded-xl border border-slate-300 bg-white hover:bg-slate-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"><span class="h-1 w-1 rounded-full bg-slate-900 shadow-[-7px_0_0_#0f172a,7px_0_0_#0f172a]"></span></button>
</div>

06. Tailwind Hamburger Dropdown

TailwindDropdown

A small-site menu where the hamburger drops a list of links below the button instead of opening a full panel. It closes on outside click and Escape, and the links keep visible focus styles on the dark background.

View code
<div class="relative" id="twhd">
  <button aria-expanded="false" aria-controls="twhd-l" class="inline-flex items-center gap-2 rounded-lg border border-slate-700 bg-slate-900 px-4 py-2.5 text-sm font-bold text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-400"><span aria-hidden="true">&#9776;</span> Menu</button>
  <ul id="twhd-l" hidden class="absolute left-0 mt-1.5 w-48 rounded-xl border border-slate-700 bg-slate-950 p-1.5 text-sm">
    <li><a href="#" class="block rounded-lg px-3 py-2 text-slate-200 hover:bg-slate-800 focus:bg-slate-800 focus:outline-none">Recipes</a></li>
    <li><a href="#" class="block rounded-lg px-3 py-2 text-slate-200 hover:bg-slate-800 focus:bg-slate-800 focus:outline-none">Meal plans</a></li>
    <li><a href="#" class="block rounded-lg px-3 py-2 text-slate-200 hover:bg-slate-800 focus:bg-slate-800 focus:outline-none">About</a></li>
  </ul>
</div>
const hb = document.querySelector('#twhd button'), hl = document.getElementById('twhd-l');
function set(o) { hl.hidden = !o; hb.setAttribute('aria-expanded', String(o)); }
hb.addEventListener('click', () => set(hl.hidden));
document.addEventListener('click', e => { if (!e.target.closest('#twhd')) set(false); });
document.addEventListener('keydown', e => { if (e.key === 'Escape' && !hl.hidden) { set(false); hb.focus(); } });

About these Tailwind Hamburger Menus

Animate from aria-expanded

group-aria-expanded:rotate-45 and similar variants animate the bars from the button's own aria-expanded attribute, so the script only flips that attribute and the visual state always matches.

Panels with data attributes

The slide-out and overlay menus toggle a data-open attribute and use data-[open]: variants to show the panel, keeping all styling in the markup.

Staggered links

Each overlay link has its own delay utility such as delay-75 or delay-150, which creates the cascading entrance without custom keyframes.

Focus and Escape

When a menu opens, move focus to its first link; when Escape is pressed, close it and return focus to the button.

Frequently asked questions

Which Tailwind features are needed?

aria-* and data-* variants, available in v3.2 and later.

Do these need JavaScript?

A few lines to toggle state; the kebab icons need none.

Is there a CSS version?

Yes, see the CSS hamburger menus collection.