Dropdowns are toggleable menus attached to a button or link. They are one of the few Bootstrap components that depend on Popper, which positions the menu so it stays inside the viewport and flips when there is no room. This lesson covers the markup, menu contents, directions, alignment, auto-close behavior, and the JavaScript API, plus the mistakes that make menus open in the wrong place.
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
Account
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/profile">Profile</a></li>
<li><a class="dropdown-item" href="/settings">Settings</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="/logout">Sign out</a></li>
</ul>
</div>.dropdown provides position: relative; .btn-group also works as the wrapper..dropdown-toggle adds the caret; data-bs-toggle="dropdown" activates the plugin..dropdown-menu holds .dropdown-item elements; use <a> for links and <button> for actions.The plugin updates aria-expanded and toggles .show on both the toggle and the menu. Escape closes the menu, and arrow keys move focus between items.
| Element | Class |
|---|---|
| Section heading | .dropdown-header on an <h6> |
| Separator | <hr class="dropdown-divider"> |
| Plain text | .dropdown-item-text |
| Active item | .dropdown-item.active with aria-current="true" |
| Disabled item | .dropdown-item.disabled with aria-disabled="true" |
Forms can live inside a menu too; pad them with p-3 and use data-bs-auto-close="outside" (see below) so clicks inside do not close the menu:
<div class="dropdown-menu p-3" style="min-width: 260px">
<form>
<div class="mb-2">
<label class="form-label" for="dd-email">Email</label>
<input class="form-control" id="dd-email" type="email">
</div>
<button class="btn btn-primary w-100">Sign in</button>
</form>
</div>A split button keeps the main action separate from the toggle:
<div class="btn-group">
<button type="button" class="btn btn-success">Save</button>
<button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">Toggle save options</span>
</button>
<ul class="dropdown-menu">
<li><button class="dropdown-item">Save as draft</button></li>
<li><button class="dropdown-item">Save and publish</button></li>
</ul>
</div>Replace .dropdown on the wrapper with .dropup, .dropend or .dropstart to change where the menu opens. Alignment classes go on the menu:
.dropdown-menu-end aligns the menu's right edge with the toggle (default is left)..dropdown-menu-lg-end or .dropdown-menu-md-start change alignment per breakpoint; they require data-bs-display="static" on the toggle so Popper does not override them..dropdown-center and .dropup-center on the wrapper center the menu under the toggle.<div class="dropup">
<button class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown">Opens upward</button>
<ul class="dropdown-menu dropdown-menu-end">...</ul>
</div>data-bs-auto-close controls when the menu closes:
| Value | Closes on inside click | Closes on outside click |
|---|---|---|
| true (default) | Yes | Yes |
| inside | Yes | No |
| outside | No | Yes |
| false | No | No |
Use outside for menus containing forms or checkboxes; use false when you close the menu yourself.
.btn-sm / .btn-lg on the toggle size the button; the menu scales with the font.data-bs-theme="dark" on the .dropdown wrapper (the old .dropdown-menu-dark class is deprecated in 5.3).data-bs-offset="10,20" shifts the menu by skidding and distance in pixels.data-bs-reference="parent" positions relative to the wrapper instead of the toggle, which is useful for split buttons.import { Dropdown } from "bootstrap";
const toggle = document.querySelector("#sortToggle");
const dd = Dropdown.getOrCreateInstance(toggle, { autoClose: "outside" });
dd.show();
dd.hide();
dd.toggle();
dd.update(); // re-run Popper after the toggle moved
toggle.addEventListener("shown.bs.dropdown", () => console.log("open"));
toggle.addEventListener("hidden.bs.dropdown", (e) => console.log("closed by", e.clickEvent));Events fire on the toggle: show, shown, hide, hidden with the .bs.dropdown suffix.
overflow: hidden or overflow: auto (including .table-responsive) cut off the menu. Add data-bs-boundary="viewport" or move the dropdown outside the clipped container.bootstrap.min.js without @popperjs/core throws when the dropdown initializes; use the bundle..dropdown-menu-end not working in a navbar. Responsive alignment needs data-bs-display="static"; plain dropdown-menu-end works without it.<a> inside <button> items. Pick one element per item.Which library does the dropdown plugin use to position menus?
.dropdown wrapper with a data-bs-toggle="dropdown" toggle and a .dropdown-menu of .dropdown-item links or buttons..dropup, .dropend, .dropstart, .dropdown-menu-end and .dropdown-center control direction and alignment; responsive alignment needs data-bs-display="static".data-bs-auto-close decides which clicks close the menu; data-bs-theme="dark" styles dark menus.Next lesson: Breadcrumbs and Pagination - show the user's location in a hierarchy and move between pages of results.