Dropdown
A Tailwind CSS dropdown component for displaying a list of actions or options.
<div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
Options
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">New file</a>
<a href="#" class="dropdown-item">Copy link</a>
<div class="dropdown-separator"></div>
<a href="#" class="dropdown-item">Edit</a>
<a href="#" class="dropdown-item">Rename</a>
<div class="dropdown-separator"></div>
<a href="#" class="dropdown-item">Delete</a>
</div>
</div>With icons
Add icons to dropdown items for better visual hierarchy.
<div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
Options
</button>
<div class="dropdown-menu">
<a href="#" 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="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path><path d="M9 15h6"></path><path d="M12 18v-6"></path></svg>
New file
</a>
<a href="#" 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 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
Copy link
</a>
<div class="dropdown-separator"></div>
<a href="#" 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><path d="m15 5 4 4"></path></svg>
Edit
</a>
<a href="#" 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 20h-1a2 2 0 0 1-2-2 2 2 0 0 1-2 2H6"></path><path d="M13 8h7a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-7"></path><path d="M5 16H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1"></path><path d="M6 4h1a2 2 0 0 1 2 2 2 2 0 0 1 2-2h1"></path><path d="M9 6v12"></path></svg>
Rename
</a>
<div class="dropdown-separator"></div>
<a href="#" 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 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"></path><path d="M3 6h18"></path><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
Delete
</a>
</div>
</div>With labels
Use .dropdown-label to group items with a heading.
<div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
My Account
</button>
<div class="dropdown-menu">
<div class="dropdown-label">Settings</div>
<a href="#" 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"></path><circle cx="12" cy="7" r="4"></circle></svg>
Profile
</a>
<a href="#" 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"></rect><line x1="2" x2="22" y1="10" y2="10"></line></svg>
Billing
</a>
<a href="#" 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><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"></path></svg>
Notifications
</a>
<div class="dropdown-separator"></div>
<div class="dropdown-label">Help</div>
<a href="#" 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 7v14"></path><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"></path></svg>
Documentation
</a>
<a href="#" 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 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3"></path></svg>
Support
</a>
</div>
</div>Disabled items
Use aria-disabled="true" to disable an item. Add tabindex="-1" to prevent tab navigation to the item.
<div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
Actions
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Edit</a>
<a href="#" class="dropdown-item" aria-disabled="true" tabindex="-1"
>Duplicate</a
>
<a href="#" class="dropdown-item">Archive</a>
<div class="dropdown-separator"></div>
<a href="#" class="dropdown-item" aria-disabled="true" tabindex="-1"
>Delete</a
>
</div>
</div>Placement
Use data-sp-placement to control the dropdown position (default is bottom-end).
<div class="dropdown" data-sp-placement="bottom-start">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
bottom-start
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="bottom">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
bottom
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="bottom-end">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
bottom-end
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="top-start">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
top-start
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="top">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
top
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="top-end">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
top-end
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="left-start">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
left-start
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="left">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
left
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="left-end">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
left-end
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="right-start">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
right-start
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="right">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
right
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-placement="right-end">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
right-end
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>Offset
Use data-sp-offset to control the distance between the trigger and the menu (default is 4).
<div class="dropdown" data-sp-offset="0">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
No Offset
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
Default (4)
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>
<div class="dropdown" data-sp-offset="12">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
Offset 12
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
</div>
</div>How it works
The dropdown component uses a small JavaScript module that handles opening, closing, positioning, and keyboard navigation.
Structure
A dropdown consists of three parts:
.dropdown- Container that wraps the trigger and menu[data-sp-toggle="dropdown"]- Button that opens/closes the menu.dropdown-menu- The menu panel with items
<div class="dropdown">
<button type="button" data-sp-toggle="dropdown" aria-expanded="false">
Open Menu
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Item 1</a>
<a href="#" class="dropdown-item">Item 2</a>
</div>
</div>Opening and closing
Use data attributes to control the dropdown without writing JavaScript.
Add data-sp-toggle="dropdown" to the trigger button. The JavaScript will find the .dropdown-menu sibling and toggle it:
<button data-sp-toggle="dropdown" aria-expanded="false">Open</button>Clicking outside the dropdown or pressing Escape closes the menu. Clicking an item also closes the dropdown by default.
For programmatic control, use the global StartingPointUI.dropdown module:
const dropdown = document.querySelector(".dropdown");
StartingPointUI.dropdown.open(dropdown);
StartingPointUI.dropdown.close(dropdown);
StartingPointUI.dropdown.toggle(dropdown);Animation
The dropdown includes a default fade and zoom animation. When opened, the JavaScript sets data-state="open" on the menu element.
To customize animations, add no-animation to disable the defaults and use your own classes with data-[state=open]: selectors:
<div class="dropdown-menu no-animation data-[state=open]:animate-in data-[state=open]:slide-in-from-top-2">
<!-- Custom slide animation -->
</div><div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
Default
</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
<a href="#" class="dropdown-item">Logout</a>
</div>
</div>
<div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
No Animation
</button>
<div class="dropdown-menu no-animation">
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
<a href="#" class="dropdown-item">Logout</a>
</div>
</div>
<div class="dropdown">
<button
class="btn btn-outline"
type="button"
data-sp-toggle="dropdown"
aria-expanded="false"
>
Slide from Top
</button>
<div
class="dropdown-menu no-animation data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-top-2"
>
<a href="#" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Settings</a>
<a href="#" class="dropdown-item">Logout</a>
</div>
</div>The default animations use tw-animate-css utilities. You can customize or replace these with your own animations.
Accessibility
The dropdown JavaScript module provides full keyboard navigation and proper ARIA attributes.
For proper accessibility, add aria-expanded="false" to the trigger button:
<button data-sp-toggle="dropdown" aria-expanded="false">Open</button>The JavaScript will automatically update aria-expanded when the dropdown opens and closes.
Keyboard navigation
| Key | Action |
|---|---|
Enter / Space | Opens/closes dropdown when trigger is focused |
Escape | Closes the dropdown |
ArrowDown | Move focus to next item |
ArrowUp | Move focus to previous item |
Home | Move focus to first item |
End | Move focus to last item |
Class reference
All available classes for the dropdown component.
| Class | Description |
|---|---|
dropdown | Container for the dropdown |
dropdown-menu | The menu panel that appears on toggle |
dropdown-item | Individual menu item |
dropdown-label | Label/heading for grouping items |
dropdown-separator | Horizontal divider between items |
no-animation | Disables default animation on dropdown-menu |
<div class="dropdown">
<button data-sp-toggle="dropdown">Open</button>
<div class="dropdown-menu">
<div class="dropdown-label">Group</div>
<a href="#" class="dropdown-item">Item</a>
<div class="dropdown-separator"></div>
<a href="#" class="dropdown-item">Item</a>
</div>
</div>Data attributes
All data attributes for the dropdown component.
| Attribute | Element | Description |
|---|---|---|
data-sp-toggle="dropdown" | Button | Toggles the dropdown |
data-sp-placement | .dropdown | Menu position (default: bottom-end) |
data-sp-offset | .dropdown | Distance from trigger in pixels (default: 4) |
data-state | Menu | Set to open when menu is visible |
aria-disabled="true" | Item | Disables the item visually and functionally |
<div class="dropdown" data-sp-placement="bottom-start" data-sp-offset="8">
<button data-sp-toggle="dropdown" aria-expanded="false">Open</button>
<div class="dropdown-menu">
<a href="#" class="dropdown-item">Enabled</a>
<a href="#" class="dropdown-item" aria-disabled="true">Disabled</a>
</div>
</div>