28 Tailwind hamburger menus spanning off-canvas drawers, full-screen and blur overlays, checkbox-hack and <details> zero-JS builds, animated line-to-X and morphing icons, push-page and 3D-flip canvases, floating and bottom-bar toggles, plus glassmorphism, neumorphic, and brutalist styling. Scoped under .thb-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.
Building a whole Tailwind app, not just this component?
You just browsed 28 Tailwind hamburger menus. Untitled UI Pro unlocks 5,000+ components and sections and 250+ page examples for React, styled with Tailwind CSS v4. One licence is a one-time $349 with lifetime updates; teams start at $999.
The reveal every design-award site uses, ported to variants: tap the burger and the menu grows out of the button as a perfect circle, because the panel carries its closed and open clip-path as two arbitrary utilities on one element. The state is a data-open attribute on the stage, so the panel, the icon bars and the link stagger all read it through group-data-open: — the stylesheet keeps nothing but tokens.
The WAI-ARIA disclosure-navigation pattern in utilities, and the port has a genuine win: because the open state IS aria-expanded, aria-expanded: and group-has-aria-expanded: style straight off the accessibility attribute. Style and semantics cannot drift, because there is only one source of truth. Arrow/Home/End roving focus, Escape that returns focus, no focus trap — a disclosure, not a dialog.
Four production-grade line-to-X morphs on one stage — Spin, Squeeze, Arrow and Drop — and the port deletes the variant classes entirely. There is no .spin or .squeeze rule: each tile is a group whose three bars carry their own end states as group-aria-pressed: utilities, so a variant is now a class list you copy rather than a stylesheet block you maintain.
The app-drawer everyone means when they say “hamburger menu”: a right-hand panel that slides in on translate-x (never on offsets), over a scrim that dims and blurs the page behind it. In utilities the drawer and the scrim each carry their own closed and open geometry, and the scrim stays a real <button> — so click-outside-to-close needs no document listener.
The classic zero-dependency pattern, and the port is the most instructive in the collection: peer-checked: handles the panel beautifully, but the burger's bars are descendants of a sibling — not siblings themselves — so they need arbitrary variants. That friction is exactly the argument for demo 09's has-checked:. Both accessibility fixes survive: the input stays focusable, and its focus ring is re-projected onto the visible label.
The publisher/e-commerce drawer that carries a whole header's worth of jobs — auto-focused search, nav with counts, a New badge, a social row and a pinned newsletter CTA. The port's real content is one class list: grid grid-rows-[auto_1fr_auto] on the drawer plus min-h-0 overflow-auto on the middle row, which is the whole reason feature-rich drawers stop losing their footer.
Newsletter
Enjoying these demos? Get new ones by email.
A short email when a new collection ships. Unsubscribe any time.
Real frosted glass, not grey-with-opacity — and Tailwind happens to have the exact utilities for it: backdrop-blur-[18px] backdrop-saturate-[1.7] compose into one backdrop-filter, no prefix juggling, no stacking order to remember. The stage runs drifting gradient blobs so you can see the glass working, and the mandatory @supports not fallback stays in CSS, where it belongs.
Instead of layering a drawer OVER the page, the whole canvas glides aside to reveal a menu resting beneath it — the page becomes a sheet you slide off a shelf. One element transitions; the menu never moves. In utilities the canvas's entire open state (push, 6% shrink, corner radius, deep shadow) is four group-data-open: classes sitting next to its resting state.
The checkbox hack rebuilt for the :has() era, and this is where the port pays back demo 05's friction: group-has-checked: reads the state from an ANCESTOR, so the burger, the header, the fullscreen panel and even the page content in a different subtree all respond — no sibling order, no arbitrary variants, no hook classes. Same zero-JS guarantee, none of the DOM gymnastics.
Not a rotate trick — a true shape morph. The line geometry lives in CSS as d: path(), and because that property is animatable the browser interpolates the actual coordinates from ☰ to ✕. This is also the collection's clearest example of a technique that must NOT become a utility: path data plus its @supports fallback belongs in the stylesheet, and the markup stays utility-only.
The fashion-house takeover: the menu becomes the page, and five oversized links reveal themselves line by line from under invisible masks. The technique to steal is two utilities deep — overflow-hidden on the <li>, translate-y-[110%] on the link — and in the port both halves of the reveal sit in the same class list as the stagger that drives them.
The workhorse app sidebar, structured the way real products need it: grouped sections, icon+label rows with an aria-current-driven indicator bar, shortcut hints, and a user card pinned to the bottom. The slide engine is demo 04's; what this demo teaches is interior architecture — and in utilities the active-state contract (aria-current:) is visible on the row itself.
The breakpoint swap every site ships — inline links wide, hamburger narrow — and Tailwind v4's container-query variants make it read like a sentence: @max-lg:hidden on the desktop row, @max-lg:grid on the burger. Drag the stage's right edge and watch the swap happen live. Zero JavaScript, because the toggle is a peer checkbox.
Navigation reduced to a single floating disc: a 56px FAB opening a vertical speed-dial of pill links that spring upward with staggered, slightly overshooting motion. The technique to study is that the spring is transitions only — no keyframes — so a close mid-open reverses gracefully, and in utilities the overshoot curve and the plain opacity ease are visibly split.
Newsletter
Enjoying these demos? Get new ones by email.
A short email when a new collection ships. Unsubscribe any time.
The canonical Tailwind navbar — and in this collection it is the one demo that needed no port at all, because the original was already written in utilities. What it gains here is honesty: the CSS version had to ship a hand-written shim to render those classes, and this one runs the real compiler, so what you see is exactly what hidden md:flex produces.
What the Bootstrap 5 navbar becomes when you migrate it — the same markup shape, the same breakpoint behaviour, the same animated collapse, with no framework CSS and no collapse plugin. Every Bootstrap class in the chain is mapped to its utility equivalent in the docs, so this doubles as a migration table for the most-copied navbar on the web.
The audit-proof build: a drawer implemented as a true modal dialog — role=dialog, aria-modal, focus moved in, trapped, restored, background inert, Escape wired, 44px targets, visible rings, reduced-motion path. Every requirement is tied to its WCAG success criterion, and in utilities the two that are usually missed — target size and focus visibility — are impossible to overlook because they are typed on every control.
How to animate a menu to height:auto — the question with a decade of bad answers — solved twice in utilities: the [grid-template-rows:0fr] → 1fr technique that is Baseline everywhere, and the 2026-native interpolate-size: allow-keywords written out beside it as the alternative. They are alternatives, not layers — the second one swaps the panel's display model, so this demo ships the grid version and documents the other. Zero JavaScript.
Five hover treatments for the resting burger — the micro-interaction users see a hundred times before they ever click. The port's real contribution is enforcement: every group-hover: has a group-focus-visible: twin typed immediately after it, so the keyboard gap that hover-only effects always ship is impossible to miss here.
The cinematic takeover: the article behind stays visible but slips out of focus while the links arrive through a blur-to-sharp animation with tracking that tightens as they land. Two blurs doing opposite jobs — backdrop-blur-* on the sheet, blur-* on the links — and Tailwind's naming makes the distinction, which trips up half the implementations of this effect, impossible to confuse.
The app-store staple: a four-tab bottom bar whose centre slot holds a raised floating hamburger sitting in a real curved notch cut from the bar with a CSS mask — not a fake shadow trick. Tapping it lifts a bottom sheet. The tabs are a radio group styled with has-checked:, which is the utility that makes one-of-N view switching work with no script at all.
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.
Newsletter
Enjoying these demos? Get new ones by email.
A short email when a new collection ships. Unsubscribe any time.
The layout lesson behind every navbar, taught on the navbar itself — flip the X-ray switch and the bar reveals its own construction with dashed outlines and callouts pinned to the three declarations doing all the work. In Tailwind the answer to “how do I push the hamburger right?” is two characters shorter and RTL-correct by default: ms-auto.
Five action buttons fan out along a perfect quarter-circle arc, their positions computed by the browser itself — sin() and cos() turn an index and a radius into coordinates, with no JS math and no hand-tuned offsets. This is the per-item index pattern at its most extreme: every button carries only its --i, and one arbitrary translate utility does the geometry.
The shrinking header without a scroll listener: CSS scroll-driven animations bind a keyframe track to scroll position, so the navbar compresses, the wordmark tightens, the burger slims and a frosted border fades in — all proportional to the first 140px. In utilities the animation is a token and its clock is two arbitrary properties, which reads as exactly what it is: this animation's timeline is the scroller.
Soft-UI physics done by the rules: the burger is a clay button raised by the canonical dual shadow, and pressing it does not move it — it inverts the shadows to inset, so the button sinks INTO the surface. In utilities both shadow states sit in one class list, which makes the light-source discipline that neumorphism lives by impossible to get wrong by accident.
Neo-brutalism with its rules intact: 3px black borders on everything, hard offset shadows that do not blur, one shrieking yellow, uppercase mono type — and motion that CUTS instead of eases, because in this dialect a transition curve is a lie. The press is the port's neatest line: the plate travels exactly its shadow's offset and lands flat, which is two utilities sitting next to each other.
The theatrical finale: the entire page tilts back in 3D — rotateY around its right edge with real perspective — swinging aside like a door to reveal the nav standing behind it, whose links counter-rotate into place. Three properties produce the drama, and in utilities all three are arbitrary on purpose: perspective, transform-origin and a composed transform are scene geometry, not design tokens.
FAQ
Frequently asked questions
How do you build a Tailwind hamburger menu with no JavaScript?
Three demos cover this. The checkbox hack (demo 05) pairs a visually hidden <input type=checkbox> with a <label> burger; the panel reads the state with peer-checked: variants, so ticking the box slides the menu in. Demo 09 rebuilds the same idea for the :has() era — the wrapper matches has-[:checked], so no hidden peer sibling is needed. Demo 22 goes fully semantic with nested <details> elements, so each level opens on its own <summary> with no state plumbing at all. All three are real navigation you can tab into. The trade-off: without script you cannot trap focus or restore it on close, and you cannot toggle aria-expanded, so reserve pure-CSS for simple marketing headers rather than app shells that gate real routes.
How do you animate the three-line Tailwind hamburger icon into an X?
Two approaches ship here. Demo 03 keeps three real bars and transforms them: the top and bottom rotate 45 degrees while the middle fades to opacity-0, all driven off the checked state with peer-checked:rotate-45 and matched translate-y utilities so the arms cross at centre. It offers Spin, Squeeze, Arrow and Drop timing variants on one stage. Demo 10 is a true geometry morph rather than a rotate trick — the line shape lives in CSS as d: path() and animates between the burger and the close glyph. The bug to avoid: set a transform-origin on each bar (usually centre) and give them equal height and spacing, otherwise the two arms meet off-centre and the X looks lopsided. Add motion-reduce:transition-none so the morph is instant for reduced-motion users.
How do you build a slide-in off-canvas drawer with a dimmed backdrop in Tailwind?
Demo 04 is the canonical app drawer: a fixed right-hand panel parked off-screen with translate-x-full, slid to translate-x-0 when open, over a dimmed <div> backdrop that fades from opacity-0 to a semi-opaque black. Demo 12 extends it into a grouped sidebar with icon-and-label rows. The backdrop is not decoration — it is the click-to-close target and it visually mutes the page beneath. Two common mistakes: forgetting overflow-hidden on <body> while open, so the page behind scrolls under the drawer; and animating left or width instead of transform, which repaints every frame and stutters on mobile. Keep the panel on transform and the backdrop on opacity so both run on the compositor, and give the panel a high z-index with the backdrop one just below it.
Why won't my Tailwind hamburger menu animate to height auto?
Demo 18 exists for exactly this. You cannot transition to height: auto — the browser has no numeric target to interpolate toward, so the menu snaps open instead of sliding. The fix is grid-template-rows: wrap the links in a grid that animates from grid-rows-[0fr] to grid-rows-[1fr], with the inner element set to overflow-hidden and min-h-0. The row track has a resolvable size at both ends, so it animates smoothly and still collapses to the content's real height when open. The old max-height hack works too but forces you to guess a ceiling — too low clips long menus, too high adds a lazy pause at the start of the slide. The grid technique needs no magic number. Pair it with min-h-0 or the inner content refuses to shrink below its intrinsic height and nothing animates.
How do I make a Tailwind hamburger menu keyboard and screen-reader accessible?
Demos 02 and 17 are the accessible builds. Demo 02 follows the WAI-ARIA disclosure pattern: the burger is a real <button> carrying aria-expanded and aria-controls pointing at the panel id, toggled in a few lines of script. Demo 17 goes further and implements the drawer as a modal <dialog> with role=dialog and aria-modal, which gives you the browser's own focus trap and Escape-to-close for free. The rules either way: the toggle must be a <button>, not a <div> with a click handler; the icon needs an aria-label like Menu since it has no text; decorative bars get aria-hidden; and on open you move focus into the panel, on close you return it to the button. Pure-CSS variants cannot do focus management, so use these two whenever the menu gates real application navigation.
How do you show inline links on desktop but a hamburger on mobile in Tailwind?
Demos 13, 15 and 16 all solve the responsive swap. The pattern is one set of inline links hidden below your breakpoint and shown above it, plus a hamburger doing the reverse: hidden md:flex on the link row and md:hidden on the burger. Pick the breakpoint by content, not device — the moment the links would wrap or crowd the logo is where the burger should appear, which is often lg for link-heavy bars rather than the default md. Demo 16 shows the same shape migrated from a Bootstrap navbar, so the markup feels familiar. The bug people hit: styling the mobile panel and the desktop row as one element, then fighting specificity. Keep them as two separate blocks toggled purely by breakpoint utilities, and let the mobile panel own its open and close state independently of the always-on desktop row.
How do you get a real glassmorphism backdrop-blur hamburger menu in Tailwind?
Demo 07 is genuine frosted glass, not grey-with-opacity. The panel takes a translucent background plus backdrop-blur, so the page behind is sampled and blurred through it — Tailwind maps this straight to backdrop-blur-md and a bg-white/10-style tint. Demo 20 uses the same blur as a full-screen takeover where the article behind stays legible but slips out of focus. Two things to know: backdrop-filter needs the -webkit- prefix for older Safari, which Tailwind emits for you; and the effect is invisible unless there is actual content behind the panel to blur, so it does nothing over a flat solid page. Blur is also GPU-cost per frame — fine for a menu that opens occasionally, wasteful on something that animates constantly. Add a faint border-white/20 to define the glass edge, otherwise it melts into the background.
When should I not use a full-screen or animated Tailwind hamburger menu?
Match the pattern to the context. The full-screen overlay (demo 11) and 3D flip (demo 28) are dramatic, but they hijack the whole viewport — wrong for a dashboard where users switch sections constantly and just want a persistent sidebar like demo 12. The push-page menu (demo 08) shifts the entire canvas aside, which feels great on a simple site but breaks any layout with fixed or sticky elements, since those shift too. Never hide primary navigation behind a burger on a wide desktop where the links comfortably fit — demo 13's breakpoint swap keeps them inline there and only collapses when space runs out. And skip the heavy reveals — clip-path expansion, radial ripple, 3D tilt — on content users hit dozens of times a day; the animation that delights once becomes friction on the hundredth open. Reserve spectacle for marketing, use plain drawers for apps.