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

Dropdowns

CSSHTMLTailwindBootstrapUIIntermediate🎯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.