Starting Point
v0.33.1

Search documentation

Search for a page and jump to it.

Start typing to search...
Go to Page
escClose

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.

ClassDescription
dropdownAdd to the menu panel, which carries the data-sp-* options
dropdown-labelAdd to a heading above a group of items
dropdown-itemAdd to each action, on a native <button> or <a>
dropdown-item-destructiveAdd to dropdown-item for a destructive action
dropdown-item-checkboxAdd to dropdown-item wrapping a hidden <input type="checkbox"> that holds the state
dropdown-item-radioAdd to dropdown-item wrapping a hidden <input type="radio"> with a shared name
dropdown-shortcutAdd to a <span> inside an item for a keyboard hint
dropdown-separatorAdd to an element between items to divide them
dropdown-subAdd to a nested dropdown that opens from an item
<!-- 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.

<button id="dd-basic-trigger" class="btn btn-outline">Open</button>
 
<div class="dropdown" data-sp-toggle="#dd-basic-trigger">
  <button class="dropdown-item">Profile</button>
  <button class="dropdown-item">Billing</button>
  <button class="dropdown-item">Settings</button>
</div>

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>

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>

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.

<button id="dd-disabled-trigger" class="btn btn-outline">Open</button>
 
<div class="dropdown" data-sp-toggle="#dd-disabled-trigger">
  <button class="dropdown-item">Profile</button>
  <button class="dropdown-item">Billing</button>
  <button class="dropdown-item" aria-disabled="true">API</button>
</div>

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>

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.

<button id="dd-hover-trigger" class="btn btn-outline">Hover me</button>
 
<div class="dropdown" data-sp-toggle="#dd-hover-trigger" data-sp-mode="hover">
  <button class="dropdown-item">Profile</button>
  <button class="dropdown-item">Settings</button>
  <button class="dropdown-item">Logout</button>
</div>

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

Set each option with its own data-sp-* attribute on the dropdown element.

AttributeValuesDefault
data-sp-toggleCSS selectorNone
data-sp-placementFloating UI placementbottom-end
data-sp-offsetNumber4
data-sp-modeclick | hoverclick
data-sp-match-widthBooleanfalse
data-sp-itemCSS selector.dropdown-item
<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.

EventWhen
sp-beforeshowBefore opening (cancelable)
sp-showOpening
sp-shownOpen and settled
sp-beforehideBefore closing (cancelable)
sp-hideClosing
sp-hiddenClosed
el.addEventListener("sp-beforehide", (e) => {
  if (unsavedChanges) e.preventDefault(); // veto the close
});

Methods

Get the instance with sp.dropdown(el), then call its methods:

MethodDescription
show()Open the menu
hide()Close the menu
toggle()Open if closed, else close
const dropdown = sp.dropdown(document.querySelector("#my-dropdown"));
 
dropdown.show();