Tailwind CSS Dropdown Menu
Use the dropdown component to show a menu of actions behind a trigger, like a user menu or the commands behind a "more" button. For rich free-form content, reach for the popover, and for picking a value in a form, the select or combobox.
<button id="dd-demo-trigger" class="btn btn-outline">Open</button>
<div class="dropdown w-44" data-sp-toggle="#dd-demo-trigger">
<div class="dropdown-label">My Account</div>
<button class="dropdown-item">
Profile
<span class="dropdown-shortcut">⇧⌘P</span>
</button>
<button class="dropdown-item">
Billing
<span class="dropdown-shortcut">⌘B</span>
</button>
<button id="dd-demo-invite" class="dropdown-item">
Invite users
<svg class="ms-auto rtl:rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item">
Log out
<span class="dropdown-shortcut">⇧⌘Q</span>
</button>
</div>
<div
class="dropdown dropdown-sub"
data-sp-toggle="#dd-demo-invite"
data-sp-mode="hover"
data-sp-placement="right-start"
>
<button class="dropdown-item">Email</button>
<button class="dropdown-item">Message</button>
<button class="dropdown-item">Copy link</button>
</div>Usage
Add the dropdown class to the menu panel and point it at its trigger with data-sp-toggle. It opens on click and closes when an action is chosen, on an outside click, or with Escape.
<!-- This is the trigger -->
<button id="my-trigger" class="btn btn-outline">Open</button>
<!-- This is the dropdown -->
<div class="dropdown" data-sp-toggle="#my-trigger">
<button class="dropdown-item">Profile</button>
<button class="dropdown-item">Settings</button>
</div>Examples
Basic dropdown
A plain menu of actions.
Dropdown groups
Group related items under a dropdown-label and divide groups with a dropdown-separator.
<button id="dd-groups-trigger" class="btn btn-outline">Open</button>
<div class="dropdown" data-sp-toggle="#dd-groups-trigger">
<div class="dropdown-label">My Account</div>
<button class="dropdown-item">Profile</button>
<button class="dropdown-item">Billing</button>
<button class="dropdown-item">Settings</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item">GitHub</button>
<button class="dropdown-item">Support</button>
</div>Dropdown submenu
Nest menus by pointing a second dropdown at an item and adding dropdown-sub. Hover mode opens it when the pointer reaches the item.
<button id="dd-sub-trigger" class="btn btn-outline">Open</button>
<div class="dropdown" data-sp-toggle="#dd-sub-trigger">
<button class="dropdown-item">Team</button>
<button id="dd-sub-invite" class="dropdown-item">
Invite users
<svg class="ml-auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</button>
<button class="dropdown-item">
New Team
<span class="dropdown-shortcut">⌘+T</span>
</button>
</div>
<div
class="dropdown dropdown-sub"
data-sp-toggle="#dd-sub-invite"
data-sp-mode="hover"
data-sp-placement="inline-end-start"
>
<button class="dropdown-item">Email</button>
<button class="dropdown-item">Message</button>
<button id="dd-sub-more" class="dropdown-item">
More options
<svg class="ml-auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item">Advanced...</button>
</div>
<div
class="dropdown dropdown-sub"
data-sp-toggle="#dd-sub-more"
data-sp-mode="hover"
data-sp-placement="inline-end-start"
>
<button class="dropdown-item">Calendly</button>
<button class="dropdown-item">Slack</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item">Webhook</button>
</div>Keyboard shortcuts
Hint an item's keyboard shortcut with a dropdown-shortcut at its end.
<button id="dd-shortcuts-trigger" class="btn btn-outline">Open</button>
<div class="dropdown" data-sp-toggle="#dd-shortcuts-trigger">
<div class="dropdown-label">My Account</div>
<button class="dropdown-item">
Profile
<span class="dropdown-shortcut">⇧⌘P</span>
</button>
<button class="dropdown-item">
Billing
<span class="dropdown-shortcut">⌘B</span>
</button>
<button class="dropdown-item">
Settings
<span class="dropdown-shortcut">⌘S</span>
</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item">
Log out
<span class="dropdown-shortcut">⇧⌘Q</span>
</button>
</div>Dropdown items with icons
Lead items with an icon, sized automatically.
<button id="dd-icons-trigger" class="btn btn-outline">Open</button>
<div class="dropdown" data-sp-toggle="#dd-icons-trigger">
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
Profile
</button>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/></svg>
Billing
</button>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/></svg>
Settings
</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item dropdown-item-destructive">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 17 5-5-5-5"/><path d="M21 12H9"/><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/></svg>
Log out
</button>
</div>Checkbox items
Make items checkable with dropdown-item-checkbox. A hidden checkbox input holds the state, so checked, change events, and form submission work like any input, and toggling keeps the menu open.
<button id="dd-check-trigger" class="btn btn-outline">Open</button>
<div class="dropdown w-40" data-sp-toggle="#dd-check-trigger">
<div class="dropdown-label">Appearance</div>
<div class="dropdown-item dropdown-item-checkbox">
<input type="checkbox" name="statusbar" checked />
Status Bar
</div>
<div class="dropdown-item dropdown-item-checkbox" aria-disabled="true">
<input type="checkbox" name="activitybar" />
Activity Bar
</div>
<div class="dropdown-item dropdown-item-checkbox">
<input type="checkbox" name="panel" />
Panel
</div>
</div>Radio items
Give dropdown-item-radio inputs a shared name and the browser keeps the set exclusive. Read the choice with input[name=position]:checked.
<button id="dd-radio-trigger" class="btn btn-outline">Open</button>
<div class="dropdown w-32" data-sp-toggle="#dd-radio-trigger">
<div class="dropdown-label">Panel Position</div>
<div class="dropdown-item dropdown-item-radio">
<input type="radio" name="position" value="top" />
Top
</div>
<div class="dropdown-item dropdown-item-radio">
<input type="radio" name="position" value="bottom" checked />
Bottom
</div>
<div class="dropdown-item dropdown-item-radio">
<input type="radio" name="position" value="right" />
Right
</div>
</div>Destructive items
Mark a dangerous action with dropdown-item-destructive.
<button id="dd-destructive-trigger" class="btn btn-outline">Actions</button>
<div class="dropdown" data-sp-toggle="#dd-destructive-trigger">
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/></svg>
Edit
</button>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v13"/><path d="m16 6-4-4-4 4"/><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"/></svg>
Share
</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item dropdown-item-destructive">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
Delete
</button>
</div>Disabled
Add aria-disabled to disable an item.
Avatar dropdown
Any element can be the trigger, like an avatar button for a user menu.
<button id="dd-avatar-trigger" class="btn btn-ghost btn-icon rounded-full">
<span class="avatar">
<img
class="avatar-image"
src="https://images.unsplash.com/photo-1750390200282-bf7f669a9946?w=640&h=640&fit=facearea&facepad=3.2&auto=format&q=100"
alt="Leila Navarro"
/>
<span class="avatar-fallback">LN</span>
</span>
</button>
<div class="dropdown" data-sp-toggle="#dd-avatar-trigger">
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"/><path d="m9 12 2 2 4-4"/></svg>
Account
</button>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/></svg>
Billing
</button>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.268 21a2 2 0 0 0 3.464 0"/><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"/></svg>
Notifications
</button>
<div class="dropdown-separator"></div>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 17 5-5-5-5"/><path d="M21 12H9"/><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/></svg>
Sign Out
</button>
</div>Complex dropdown
Groups, submenus, checkboxes, and radio items compose into a full application menu.
<button id="dd-complex-trigger" class="btn btn-outline">Open</button>
<div class="dropdown w-44" data-sp-toggle="#dd-complex-trigger">
<div class="dropdown-label">File</div>
<button class="dropdown-item">
New File
<span class="dropdown-shortcut">⌘N</span>
</button>
<button class="dropdown-item">
Save
<span class="dropdown-shortcut">⌘S</span>
</button>
<div class="dropdown-separator"></div>
<div class="dropdown-label">View</div>
<div class="dropdown-item dropdown-item-checkbox">
<input type="checkbox" name="sidebar" checked />
Show Sidebar
</div>
<div class="dropdown-item dropdown-item-checkbox">
<input type="checkbox" name="statusbar" />
Show Status Bar
</div>
<div class="dropdown-separator"></div>
<button id="dd-complex-theme" class="dropdown-item">
Theme
<svg class="ml-auto" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</button>
</div>
<div
class="dropdown dropdown-sub"
data-sp-toggle="#dd-complex-theme"
data-sp-mode="hover"
data-sp-placement="inline-end-start"
>
<div class="dropdown-label">Appearance</div>
<div class="dropdown-item dropdown-item-radio">
<input type="radio" name="theme" value="light" checked />
Light
</div>
<div class="dropdown-item dropdown-item-radio">
<input type="radio" name="theme" value="dark" />
Dark
</div>
<div class="dropdown-item dropdown-item-radio">
<input type="radio" name="theme" value="system" />
System
</div>
</div>Dropdown placement
Set where the menu opens relative to its trigger with data-sp-placement. It accepts any Floating UI placement, like top, right-start, or bottom-end, plus the logical sides inline-start and inline-end that follow the text direction. The menu flips to the opposite side on its own when there isn't room.
<div class="flex gap-6">
<button id="dd-placement-start" class="btn btn-outline btn-sm">Start</button>
<button id="dd-placement-center" class="btn btn-outline btn-sm">
Center
</button>
<button id="dd-placement-end" class="btn btn-outline btn-sm">End</button>
</div>
<div
class="dropdown w-40"
data-sp-toggle="#dd-placement-start"
data-sp-placement="bottom-start"
>
<button class="dropdown-item">Profile</button>
<button class="dropdown-item">Settings</button>
</div>
<div
class="dropdown w-40"
data-sp-toggle="#dd-placement-center"
data-sp-placement="bottom"
>
<button class="dropdown-item">Profile</button>
<button class="dropdown-item">Settings</button>
</div>
<div
class="dropdown w-40"
data-sp-toggle="#dd-placement-end"
data-sp-placement="bottom-end"
>
<button class="dropdown-item">Profile</button>
<button class="dropdown-item">Settings</button>
</div>Open on hover
Add data-sp-mode="hover" to open the menu on hover instead of click. It closes when the pointer leaves both the trigger and the menu.
RTL
Add dir="rtl" to any parent element, typically <html>, to render right-to-left. Flip directional icons with rtl:rotate-180. See the RTL guide for details.
<div id="dd-rtl-demo" dir="rtl">
<button id="dd-rtl-trigger" class="btn btn-outline" data-i18n="open">افتح القائمة</button>
<div class="dropdown" data-sp-toggle="#dd-rtl-trigger">
<button id="dd-rtl-account" class="dropdown-item">
<span data-i18n="account">الحساب</span>
<svg class="ms-auto rtl:rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</button>
<div class="dropdown-separator"></div>
<div class="dropdown-label" data-i18n="team">الفريق</div>
<button class="dropdown-item">
<span data-i18n="newTeam">فريق جديد</span>
<span class="dropdown-shortcut">⌘+T</span>
</button>
<div class="dropdown-separator"></div>
<div class="dropdown-item dropdown-item-checkbox">
<input type="checkbox" name="dd-rtl-status" checked />
<span data-i18n="showStatus">إظهار الحالة</span>
</div>
</div>
<div
class="dropdown dropdown-sub"
data-sp-toggle="#dd-rtl-account"
data-sp-mode="hover"
data-sp-placement="inline-end-start"
>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span data-i18n="profile">الملف الشخصي</span>
</button>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/></svg>
<span data-i18n="billing">الفوترة</span>
</button>
<button class="dropdown-item">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/></svg>
<span data-i18n="settings">الإعدادات</span>
</button>
</div>
</div>
<script>
const translations = {
ar: { dir: "rtl", open: "افتح القائمة", account: "الحساب", team: "الفريق", newTeam: "فريق جديد", showStatus: "إظهار الحالة", profile: "الملف الشخصي", billing: "الفوترة", settings: "الإعدادات" },
he: { dir: "rtl", open: "פתח תפריט", account: "חשבון", team: "הצוות", newTeam: "צוות חדש", showStatus: "הצג סטטוס", profile: "פרופיל", billing: "חיוב", settings: "הגדרות" },
en: { dir: "ltr", open: "Open menu", account: "Account", team: "Team", newTeam: "New Team", showStatus: "Show status", profile: "Profile", billing: "Billing", settings: "Settings" },
};
window.addEventListener("message", (e) => {
const t = translations[e.data?.lang];
if (e.data?.type !== "sp-language" || !t) return;
document.getElementById("dd-rtl-demo").dir = t.dir;
document.querySelectorAll("[data-i18n]").forEach((el) => {
el.textContent = t[el.dataset.i18n];
});
});
</script>Options
Dropdown
Set each option with its own data-sp-* attribute on the dropdown element.
<div
class="dropdown"
data-sp-toggle="#my-trigger"
data-sp-placement="bottom-start"
></div>JavaScript
Events
Lifecycle events fire on the dropdown element. The before* events are cancelable.
el.addEventListener("sp-beforehide", (e) => {
if (unsavedChanges) e.preventDefault(); // veto the close
});Methods
Get the instance with sp.dropdown(el), then call its methods:
const dropdown = sp.dropdown(document.querySelector("#my-dropdown"));
dropdown.show();