|$ curl https://forge-ai.dev/api/markdown?path=docs/components/dropdowns
$cat docs/dropdowns.md
updated Recently·16 min read·published

Dropdowns

◆CSS◆HTML◆Tailwind◆Bootstrap◆UI◆Intermediate🎯Free Tools
Introduction

Dropdown menus save space by hiding actions until the user needs them. This guide covers production-ready dropdown patterns in plain HTML/CSS, Tailwind CSS, and Bootstrap — including hover and click triggers, icons, headers, nested submenus, split buttons, sizing, positioning, and accessibility.

ℹ

info

Prefer click triggers over hover on touch devices. Use aria-expanded to communicate open/closed state to screen readers.
Hover Dropdown

Pure CSS dropdown that opens on hover — no JavaScript required. Best for desktop navigation with mouse users.

hover-dropdown
Live
untitled.html
HTML
1<div class="wrapper">
2 <div class="dropdown">
3 <button class="trigger">
4 File ▾
5 </button>
6 <div class="menu">
7 <a href="#" class="item">
8 New File
9 <span class="shortcut">
10 ⌘N
11 </span>
12 </a>
13 <a href="#" class="item">
14 Open...
15 <span class="shortcut">
16 ⌘O
17 </span>
18 </a>
19 <div class="divider">
20 </div>
21 <a href="#" class="item">
22 Save
23 <span class="shortcut">
24 ⌘S
25 </span>
26 </a>
27 <a href="#" class="item">
28 Save As...
29 <span class="shortcut">
30 ⇧⌘S
31 </span>
32 </a>
33 <div class="divider">
34 </div>
35 <a href="#" class="item danger">
36 Close
37 </a>
38 </div>
39 </div>
40 <div class="dropdown">
41 <button class="trigger">
42 Edit ▾
43 </button>
44 <div class="menu">
45 <a href="#" class="item">
46 Undo
47 <span class="shortcut">
48 ⌘Z
49 </span>
50 </a>
51 <a href="#" class="item">
52 Redo
53 <span class="shortcut">
54 ⇧⌘Z
55 </span>
56 </a>
57 <div class="divider">
58 </div>
59 <a href="#" class="item">
60 Cut
61 <span class="shortcut">
62 ⌘X
63 </span>
64 </a>
65 <a href="#" class="item">
66 Copy
67 <span class="shortcut">
68 ⌘C
69 </span>
70 </a>
71 <a href="#" class="item">
72 Paste
73 <span class="shortcut">
74 ⌘V
75 </span>
76 </a>
77 </div>
78 </div>
79</div>
preview
Click Toggle

Dropdown with JavaScript click toggle — stays open until the trigger is clicked again or the user clicks outside. Works reliably on mobile and desktop.

click-dropdown
Live
untitled.html
HTML
1<div class="wrapper">
2 <div class="click-dropdown">
3 <button class="trigger" data-toggle>
4 Account ▾
5 </button>
6 <div class="click-menu" id="account-menu">
7 <div class="menu-header">
8 <div class="avatar">
9 JD
10 </div>
11 <div>
12 <div class="name">
13 Jane Doe
14 </div>
15 <div class="email">
16 jane@example.com
17 </div>
18 </div>
19 </div>
20 <div class="divider">
21 </div>
22 <a href="#" class="item">
23 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
24 <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
25 <circle cx="12" cy="7" r="4"/>
26 </svg>
27 Profile
28 </a>
29 <a href="#" class="item">
30 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
31 <circle cx="12" cy="12" r="3"/>
32 <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
33 </svg>
34 Settings
35 </a>
36 <a href="#" class="item">
37 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
38 <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
39 <polyline points="16 17 21 12 16 7"/>
40 <line x1="21" y1="12" x2="9" y2="12"/>
41 </svg>
42 Sign Out
43 </a>
44 </div>
45 </div>
46 <div class="click-dropdown">
47 <button class="trigger" data-toggle>
48 Actions ▾
49 </button>
50 <div class="click-menu">
51 <a href="#" class="item">
52 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
53 <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>
54 </svg>
55 Quick Action
56 </a>
57 <a href="#" class="item">
58 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
59 <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
60 <polyline points="14 2 14 8 20 8"/>
61 </svg>
62 Export
63 </a>
64 <a href="#" class="item danger">
65 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14">
66 <polyline points="3 6 5 6 21 6"/>
67 <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
68 </svg>
69 Delete
70 </a>
71 </div>
72 </div>
73</div>
preview
Nested Submenus

Multi-level dropdown with submenus that open on hover. Keep nesting shallow — two levels is usually enough.

nested
Live
untitled.html
HTML
1<div class="wrapper">
2 <div class="nested-drop">
3 <button class="trigger">
4 Menu ▾
5 </button>
6 <div class="nested-menu">
7 <a href="#" class="item">
8 Dashboard
9 </a>
10 <a href="#" class="item">
11 Analytics
12 </a>
13 <div class="has-sub">
14 <a href="#" class="item">
15 Reports ▸
16 </a>
17 <div class="submenu">
18 <a href="#" class="item">
19 Sales Report
20 </a>
21 <a href="#" class="item">
22 User Report
23 </a>
24 <a href="#" class="item">
25 Error Report
26 </a>
27 <div class="divider">
28 </div>
29 <a href="#" class="item">
30 Custom Report
31 </a>
32 </div>
33 </div>
34 <div class="divider">
35 </div>
36 <div class="has-sub">
37 <a href="#" class="item">
38 Settings ▸
39 </a>
40 <div class="submenu">
41 <a href="#" class="item">
42 General
43 </a>
44 <a href="#" class="item">
45 Security
46 </a>
47 <a href="#" class="item">
48 Notifications
49 </a>
50 <div class="divider">
51 </div>
52 <a href="#" class="item">
53 Advanced
54 </a>
55 </div>
56 </div>
57 <a href="#" class="item">
58 Help
59 </a>
60 </div>
61 </div>
62</div>
preview
Split Button Dropdown

Split the primary action from the dropdown menu so users can perform the most common action in one click.

split-button
Live
untitled.html
HTML
1<div class="wrapper">
2 <div class="split">
3 <button class="main">
4 Save
5 </button>
6 <button class="caret" aria-label="More save options" data-toggle>
7 ▾
8 </button>
9 <div class="menu">
10 <a href="#" class="item">
11 Save as draft
12 </a>
13 <a href="#" class="item">
14 Save and publish
15 </a>
16 <div class="divider">
17 </div>
18 <a href="#" class="item danger">
19 Discard
20 </a>
21 </div>
22 </div>
23 <div class="split outline">
24 <button class="main">
25 Export
26 </button>
27 <button class="caret" aria-label="Export options" data-toggle>
28 ▾
29 </button>
30 <div class="menu">
31 <a href="#" class="item">
32 Export as PDF
33 </a>
34 <a href="#" class="item">
35 Export as CSV
36 </a>
37 <a href="#" class="item">
38 Export as JSON
39 </a>
40 </div>
41 </div>
42</div>
preview
Sizes

Match the dropdown trigger size to the surrounding UI — small for dense tables, large for hero actions.

sizes
Live
untitled.html
HTML
1<div class="wrapper">
2 <div class="dropdown sm">
3 <button class="trigger">
4 Small ▾
5 </button>
6 <div class="menu">
7 <a href="#" class="item">
8 View
9 </a>
10 <a href="#" class="item">
11 Edit
12 </a>
13 <a href="#" class="item">
14 Delete
15 </a>
16 </div>
17 </div>
18 <div class="dropdown md">
19 <button class="trigger">
20 Default ▾
21 </button>
22 <div class="menu">
23 <a href="#" class="item">
24 View
25 </a>
26 <a href="#" class="item">
27 Edit
28 </a>
29 <a href="#" class="item">
30 Delete
31 </a>
32 </div>
33 </div>
34 <div class="dropdown lg">
35 <button class="trigger">
36 Large ▾
37 </button>
38 <div class="menu">
39 <a href="#" class="item">
40 View
41 </a>
42 <a href="#" class="item">
43 Edit
44 </a>
45 <a href="#" class="item">
46 Delete
47 </a>
48 </div>
49 </div>
50</div>
preview
Directions

Dropdowns can open up, right, or left depending on available viewport space. Use click toggles so the menu does not cover the trigger.

directions
Live
untitled.html
HTML
1<div class="wrapper">
2 <div class="click-dropdown">
3 <button class="trigger" data-toggle>
4 Dropup ▾
5 </button>
6 <div class="click-menu dropup">
7 <a href="#" class="item">
8 Item A
9 </a>
10 <a href="#" class="item">
11 Item B
12 </a>
13 <a href="#" class="item">
14 Item C
15 </a>
16 </div>
17 </div>
18 <div class="click-dropdown">
19 <button class="trigger" data-toggle>
20 Dropend ▸
21 </button>
22 <div class="click-menu dropend">
23 <a href="#" class="item">
24 Item A
25 </a>
26 <a href="#" class="item">
27 Item B
28 </a>
29 <a href="#" class="item">
30 Item C
31 </a>
32 </div>
33 </div>
34 <div class="click-dropdown">
35 <button class="trigger" data-toggle>
36 Dropstart ◂
37 </button>
38 <div class="click-menu dropstart">
39 <a href="#" class="item">
40 Item A
41 </a>
42 <a href="#" class="item">
43 Item B
44 </a>
45 <a href="#" class="item">
46 Item C
47 </a>
48 </div>
49 </div>
50</div>
preview
Accessibility

Dropdowns are interactive controls, so keyboard and screen-reader support is essential. A well-built dropdown behaves like a disclosure widget or a menu button.

  • Use a real <button> element for the trigger so it is focusable and activatable with Enter/Space.
  • Set aria-expanded to true/false on the trigger to reflect open state.
  • For navigation-style dropdowns, add aria-haspopup="menu" and manage focus inside the menu.
  • Close the menu on Escape and move focus back to the trigger.
  • Support arrow-key navigation between items and Home/End to jump to first/last item.
  • Do not rely on hover alone on touch devices; provide a click alternative.
  • Ensure color alone does not convey meaning — pair icons or text with status colors.
⚠

warning

Avoid nesting more than two levels of submenus. Deep nesting hurts keyboard navigation and mobile usability.

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.