Does Tailwind CSS have a built-in dropdown?
Not in the sense most people mean. The framework generates utility classes and state variants, and none of that includes open or close logic.
A dropdown on a Tailwind page is styled markup with behavior borrowed from elsewhere. That follows from how the framework is designed, since it produces classes and leaves interaction to the page.
The borrowing happens in a few ways. Native HTML offers details and summary, or the popover attribute. CSS state variants like group-focus-within, group-hover and peer-focus can fake a toggle. Alpine.js flips an open flag with a small script, and headless libraries (Headless UI, or the custom elements from Tailwind Plus) take over the whole job.
Tailwind Labs sells official dropdown markup in Tailwind Plus (formerly Tailwind UI). Before July 25, 2025, anyone outside React and Vue had to write the open and close script by hand.
That day the team shipped @tailwindplus/elements, a set of custom elements such as el-dropdown and el-menu that load from a single script tag. It is available exclusively to Tailwind Plus customers (Tailwind Labs, 2025).
Under the hood they all share the anatomy of a dropdown as a UI pattern. There’s a trigger and a panel with items inside it, and sometimes dividers or section headers.
Which Tailwind dropdown method fits the project?
Pick the lightest method whose failure conditions the page never meets. A single settings menu usually needs only plain HTML, while a site menu used with keyboards and screen readers needs a headless library.
| Method | Strength | Fails when |
|---|
| Plain HTML and CSS (details, focus, popover) | No script, no dependency | Outside-click close or Escape is required |
| Alpine.js | Click, outside click and Escape in a few attributes | Arrow keys and focus return are left to you |
| Headless UI | Full keyboard support and ARIA wiring | The project is Vue, where examples follow the older v1 API |
| Flowbite, Preline, daisyUI | Ready-made styled dropdowns | The design departs from the library defaults |
| Tailwind Plus Elements | Framework-free, keyboard and ARIA built in | No Tailwind Plus license |
Pure CSS techniques for dropdown menus predate utility frameworks, and the same state tricks carry over to Tailwind variants.
Flowbite is an open-source component library with a dropdown component built in. Preline takes the plugin route, a JavaScript dropdown that adds an hs-dropdown-open: variant so you can style the open state. daisyUI uses component classes and documents methods built on details and summary or on CSS focus, plus a popover API version with anchor positioning. It also has a dropdown-hover modifier.
daisyUI’s documentation says the popover method renders the menu in the browser top layer, so z-index management and overflow clipping stop mattering. Positioning then depends on CSS anchor positioning, which reached Baseline Newly available in January 2026, so the remaining constraint is any visitor on a browser older than Chrome 125, Safari 26 or Firefox 147.
For one-off menus, details and summary beat any library. The extra dependency buys nothing until outside-click close or arrow-key movement becomes a requirement.
How to build a dropdown with HTML and utility classes only
A details element wraps everything, with a summary as the trigger and an absolutely positioned panel for the menu. No script involved.
- Wrap the trigger and panel in a positioned parent. Give the details element relative, inline-block and group, so the panel positions against it and children can react to its state.
- Style the summary like a button. Add list-none to hide the default marker, then padding, rounded and ring classes. A chevron with group-open:rotate-180 shows the open state.
- Position the panel with absolute, right-0 (or left-0), z-10, mt-2 and a fixed width such as w-56. Add origin-top-right now if you plan to animate later.
- Give the panel a surface. bg-white, rounded-md, shadow-lg and ring-1 ring-black/5 is the combination Tailwind Plus uses in its own dropdown markup.
- Style the items. Each link gets block, px-4, py-2, text-sm and focus:bg-gray-100, so keyboard focus is visible.
- When menus sit side by side, give the details elements the same name attribute and only one stays open at a time (MDN, details element reference).
Since details and summary are built into HTML itself, the browser toggles the panel on Enter and Space without any script.
The approach has limits, and they show up fast.
- There’s no outside-click close. According to daisyUI’s docs, the panel opens and closes only when the summary is clicked.
- Escape does nothing.
- Utility classes alone can’t animate it. MDN says the ::details-content pseudo-element is what makes the open and close transition animatable, and it takes a little custom CSS.
- The focus-based variant (group-focus-within) closes when focus leaves, so a dialog placed inside the panel kills it.
Should a Tailwind dropdown open on hover or on click?
Click. Hover only works as an addition that also responds to click and keyboard focus.
Usability write-ups from Liquid Light and Codelight get there from different directions. Liquid Light argues that hover menus leave little room for error, and Codelight points out that a hover-only parent item hides whether it is a link or just a label.
Tailwind galleries often lean the other way, with plenty of hover-opened examples, many of them written for Tailwind CSS v3.
Click is the safer call when touch users are in the audience, when the menu holds actions rather than links, or when keyboard users have to reach the panel at all. Hover is fine on a desktop-only menu if stakeholders insist, as long as click and focus open the same panel and the parent item isn’t a link itself.
Tailwind v4 changed the footing. The hover variant now compiles inside a media query for devices whose primary input supports hover, so a v3 menu built on hidden group-hover:block stops opening on tap (Tailwind CSS upgrade guide, as of the v4.3 docs).
The same guide recommends treating hover as an enhancement. Restoring tap-to-hover takes @custom-variant hover (&:hover), and that patch does nothing for keyboard users, a gap that matters most in hover-open menus.
For site navigation, a sensible default is to build both modes and ship click, keeping hover only for clients who insist.
Hover has a second failure mode. A margin between trigger and panel leaves a dead zone where the pointer exits the hover target and the menu closes, so put padding on a wrapper around the panel instead of mt-2 on the panel.
How to add click toggling with Alpine.js and Headless UI
Alpine.js adds click toggling with an open flag, x-show and a click.outside handler. Headless UI wraps the same behavior in React components and adds keyboard handling and focus management on top.
Alpine.js click dropdown
The wrapper gets x-data=”{ open: false }” to hold the state. The trigger button gets @click=”open = !open” to flip it. The panel takes x-show=”open” with @click.outside=”open = false”, so it appears on click and closes when a click lands elsewhere.
Escape needs one more handler, @keydown.escape.window=”open = false”. The window modifier attaches the listener to the page, so Escape works wherever focus sits.
The Alpine.js docs state that click.outside is only evaluated while its element is visible. That avoids a race where the trigger click would also fire the outside handler.
Alpine does not manage arrow keys, focus return or ARIA attributes. Add them by hand or move to a headless library.
Headless UI Menu in React and Next.js
The Headless UI documentation (v2.1, as of October 2026) builds the menu out of Menu, MenuButton, MenuItems and MenuItem.
Enter, Space or an arrow key on the button opens the list, Escape closes it, and Home, End and typed letters move focus between items. Styling hooks arrive as data attributes, so data-focus:bg-blue-100 on a MenuItem highlights the active entry.
A Tailwind setup inside a React project only needs npm install @headlessui/react to start.
Positioning comes from the anchor prop. Version 2.0 integrated Floating UI directly, so anchor=”bottom start” keeps the panel in view, and –anchor-gap sets the spacing.
One default deserves attention. MenuItems sets modal to true, which locks scroll, traps focus and makes the rest of the page inert while the menu is open. Turn it off if the menu should leave the page interactive.
On Next.js 13 and later, Link works inside a MenuItem as is. Next.js 12 and older need a wrapper that forwards unknown props to the anchor, or the menu stays open after a click.
Headless UI in Vue
Vue support lags behind React. As of October 2026, the Vue link on the Headless UI site points to the v1 documentation path, while the React docs cover v2.1 with the anchor prop and data attributes.
Copy React v2 examples into Vue for the Tailwind classes only, not for the component API.
A framework-free alternative is Tailwind Plus Elements, which Tailwind Labs says works anywhere a script tag loads. It still requires the Plus license.
Making a Tailwind dropdown accessible
What an accessible dropdown needs depends on what’s inside the panel. Actions call for a menu button that announces its state and handles the keyboard the way the pattern says it should, while a list of site links is a different case. Either way, focus has to stay visible.
The W3C WAI-ARIA Authoring Practices menu button pattern covers action menus.
- The trigger gets role button, with aria-haspopup set to menu or true.
- aria-expanded is true while the panel is open and false while it’s hidden.
- The panel gets role menu, and each entry inside it gets role menuitem.
- aria-controls pointing at the panel is optional.
On the button, Enter and Space open the menu and move focus to its first item. Down Arrow or Up Arrow can do the same for the first or last item.
Writing those ARIA attributes by hand is where custom builds usually slip. A details and summary build exposes disclosure semantics only, so menu roles and the arrow-key script must be added manually.
Site navigation is where the sources split. The APG Navigation Menubar pattern draws criticism from accessibility specialists, and Adrian Roselli argues against ARIA menu roles for site nav altogether, because a misapplied role makes assistive technology misread the interface (Evinced, 2021).
Sarah Higley’s disclosure pattern sits in the middle, and the APG now includes a disclosure navigation menu example as another option. It is a button with aria-expanded, plain links inside, and Escape to close.
The workable rule across these sources is role menu for actions and disclosure for lists of links.
WCAG 1.4.13 (Level AA) sets conditions for content revealed by hover or focus. It has to be dismissible and hoverable, and it has to stay persistent (W3C).
For a hover-opened panel, dismissible means Escape closes it without moving the pointer. Most web accessibility audits check this, and a hover dropdown with no Escape handler fails it outright.
Keep a visible focus ring on the trigger and on every item, using focus-visible variants instead of stripping outlines.
Animating and theming the open and close state
Animate opacity and scale from the panel’s anchor corner. Use transition and origin-top-right, with scale-95 and opacity-0 in the closed state, and make the enter slower than the leave.
Tailwind Labs’ own dropdown markup uses 100 ms for the enter (ease-out) and 75 ms for the leave (ease-in), per the Tailwind Plus Elements example from 2025. At those durations the toggle works as a micro-interaction that users barely register.
- transition-discrete is required when the panel switches between hidden and block. It sets transition-behavior to allow-discrete, and without it the panel snaps instead of fading (Tailwind CSS docs, v4.3).
- In Headless UI, the transition prop on MenuItems adds data-closed, data-enter and data-leave attributes, which Tailwind styles through data-closed: variants.
- Wrap transition classes in motion-safe: so people with a reduced-motion setting get an instant toggle.
Dark mode follows prefers-color-scheme by default through the dark variant, and a custom variant switches it to a class or a data attribute (Tailwind CSS docs).
Give the panel, the item text and the focus highlight each a dark: counterpart. A forgotten highlight leaves light text on a light row, so check color contrast in both themes.
Put the dark class or data-theme attribute on the html element. Headless UI sets portal to true whenever anchor is used, so the panel renders outside your app wrapper and styles keyed to a wrapper div never reach it.
Why a Tailwind dropdown gets clipped or hidden behind other elements
Usually an ancestor is clipping the panel, a stacking context is trapping its z-index, or the panel runs past the viewport edge.
| Symptom | Cause | Fix |
|---|
| Panel cut off at a container edge | Ancestor with overflow-hidden or overflow-auto | Remove the overflow or move the panel to the top layer |
| Panel renders behind a sibling | z-index only counts inside its parent stacking context | Raise z-index on the ancestor, not the panel |
| z-index has no effect | An ancestor sets transform, opacity below 1, filter or isolate | Remove that property or hoist the panel out |
| Panel runs off the screen | No collision handling | Flip or shift the panel, or add position fallbacks |
Per MDN, a child’s z-index only has meaning inside its parent stacking context, and each of those properties creates one. In Tailwind terms, that means isolate, opacity-90, scale-* and blur-* on an ancestor.
The fixes run from least to most JavaScript.
- The popover attribute renders the panel in the top layer, unaffected by parent position or overflow, and an auto popover closes on outside click or Escape (MDN).
- With CSS anchor positioning, position-try-fallbacks lets the browser retry another position when the first one overflows (MDN). It has been Baseline Newly available since January 2026, though Chrome only accepts that name from version 128 (125 to 127 used position-try-options).
- Floating UI’s flip and shift middleware keep the panel inside its clipping container, and its fixed strategy in many cases lifts the panel out of a clipping ancestor (Floating UI docs).
MDN now lists the popover attribute as Baseline Widely available, with cross-browser support dated to April 2024.
Anchor positioning support is no longer the blocker it was. web.dev lists CSS anchor positioning as Baseline Newly available since Firefox 147 shipped in January 2026 (Chrome 125 and Safari 26 already supported it), and MDN marks position-try-fallbacks as Baseline 2026, newly available. Older daisyUI documentation, including the archived v5 docs site, still said Firefox and Safari did not support it, but the current daisyUI dropdown page no longer carries that warning.
Edge cases remain. The web-features dataset behind Baseline now tracks newer parts of the spec that are not yet in every browser, so check Can I use and MDN’s compatibility table for the exact properties you rely on, and keep Floating UI as the fallback for older browsers and cross-browser compatibility.
What breaks when a dropdown moves from Tailwind v3 to v4
Run the upgrade tool in a branch, then test every open state by hand (Tailwind CSS upgrade guide, v4.3 docs). Dropdown markup gets hit in a handful of places.
- Transform transitions changed. transition-[opacity,transform] no longer animates scale, so use transition-[opacity,scale]. transform-none no longer resets scale either, so use scale-none.
- Focus styles moved. outline-none now sets outline-style none, and outline-hidden keeps the invisible outline that shows in forced colors mode. The ring utility shrank from 3px to 1px and its default color moved from blue-500 to currentColor, so ring-3 plus an explicit color restores v3.
- The shadow and radius scale shifted down a step. shadow-sm became shadow-xs, shadow became shadow-sm, and rounded follows the same shift. The bare names still compile but look different.
- border-* and divide-* now default to currentColor, so item dividers turn dark unless they name a color.
- Preflight gives buttons the default cursor instead of pointer, which affects trigger buttons and button items.
- Block or flex classes no longer override the hidden attribute, so a panel toggled with the attribute must have the attribute removed.
The browser floor moved as well. Tailwind CSS v4.0 targets Safari 16.4, Chrome 111 and Firefox 128, and sites that need older browsers stay on v3.4 (Tailwind CSS upgrade guide).
The oldest Chrome and Safari versions in that floor predate the popover attribute, so a top-layer dropdown needs a fallback there. Tailwind Labs bundles polyfills in Elements for this reason, so it runs on the browsers v4.0 supports.
Tailwind Dropdown FAQ
Is the Tailwind Plus dropdown free?
No. Tailwind Plus is a paid product, and its documentation states that Tailwind Plus Elements requires a commercial license.
Open-source alternatives are Headless UI, Flowbite, Preline UI and daisyUI.
How do you build a nested dropdown?
Place a second details element inside the parent panel, or nest popover elements. MDN documents that an auto popover stays open while a nested popover opens.
Hover-opened submenus must meet the WCAG 1.4.13 conditions at every level.
What is the difference between a Menu and a Listbox?
A Menu runs actions or opens links. A Listbox picks a value that stays selected, like a form field.
Tailwind Plus Elements mirrors the split with el-dropdown for menus and el-select for form-style selects.
Does a dropdown work inside a mobile navbar?
Yes, as an inline expanding section instead of a floating panel. Headless UI and Tailwind Plus Elements both ship a disclosure component for this.
In a Tailwind navbar, Tailwind Plus uses disclosures for the mobile menu.
Do Flowbite, Preline and daisyUI dropdowns work with Tailwind v4?
Yes. Flowbite version 3.0.0 upgraded to Tailwind v4, and Flowbite React detects v3 and v4 automatically. daisyUI 5 targets v4.
Preline’s current install guide uses the v4 CSS import syntax.
Can a dropdown include icons, dividers and section headings?
Yes. In Headless UI, MenuSeparator draws the divider, and MenuSection with a MenuHeading adds labeled groups (Headless UI documentation).
Add icons as inline SVG in HTML marked aria-hidden, so screen readers announce only the item text.
What to Test Before a Tailwind Dropdown Ships
A Tailwind dropdown is ready to ship once it survives a keyboard-only pass, a tap on a touch device, a trip through clipped containers and a production build on Tailwind v4.
The order matters because each check changes what the next one shows.
- Start with the production v4 build, since renamed utilities alter every later result.
- Then go keyboard-only. It needs no extra device and catches the cheapest failures.
- Finish on a real phone inside the real page layout, where tap and clipping bugs surface.
This sequence is verified as of October 29, 2026. CSS anchor positioning is already Baseline Newly available, so the Floating UI fallback and its extra JavaScript can come out of the build once your browser targets are Chrome 128, Safari 26 and Firefox 147 or newer.
Overlay components such as a Tailwind modal face the same passes, with focus trapping added.