ScreenshotNeo

BlogHow-to

How to Create Bootstrap Dropdowns and Collapsible Elements

Build Bootstrap 5.3 dropdowns and collapsible panels with working markup, JavaScript setup, accessibility guidance, and fixes for common errors.

By the ScreenshotNeo team4 October 20269 min read

In Bootstrap 5.3, a dropdown is a click-toggled contextual menu, while a collapse component shows or hides a content region. Both need Bootstrap’s JavaScript plugin. A dropdown uses a trigger with data-bs-toggle="dropdown" and a .dropdown-menu; a collapsible panel uses data-bs-toggle="collapse", a selector pointing to the target, and the target’s .collapse class.

The examples below use Bootstrap 5.3 markup. For dropdown positioning outside a navbar, include Popper; the Bootstrap bundle includes it. The official references are the Bootstrap 5.3 dropdown documentation and Bootstrap 5.3 collapse documentation.

1. Load Bootstrap CSS and JavaScript

Add Bootstrap’s stylesheet in the document head and its JavaScript bundle before the closing body tag. The bundle includes Popper, which Bootstrap uses to position dropdowns dynamically. A navbar dropdown does not require Popper for positioning, but using the bundle is a simple way to include the needed JavaScript.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap menu and panel</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <!-- Components go here -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

For production, choose and pin the Bootstrap version your project uses, and follow its official installation guidance. Avoid loading multiple Bootstrap JavaScript versions on the same page.

2. Create a dropdown menu

Put the trigger and menu inside a .dropdown wrapper. The trigger can be a button or a link; a button is a good default for an action menu. The menu contains items styled with .dropdown-item.

<div class="dropdown">
  <button class="btn btn-secondary dropdown-toggle" type="button"
          data-bs-toggle="dropdown" aria-expanded="false">
    Choose an action
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="/first">First action</a></li>
    <li><a class="dropdown-item" href="/second">Second action</a></li>
  </ul>
</div>

Bootstrap dropdowns open by clicking, not by hovering. The trigger’s aria-expanded starts as false; Bootstrap updates it as the menu opens and closes. Use meaningful link destinations for navigation items. For actions that change page state, use buttons rather than placeholder links.

The same toggle attribute is used inside a navbar. Keep the button within the navbar’s navigation structure and retain the menu classes:

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">Example</a>
    <div class="navbar-nav">
      <div class="nav-item dropdown">
        <button class="nav-link dropdown-toggle" type="button"
                data-bs-toggle="dropdown" aria-expanded="false">
          Resources
        </button>
        <ul class="dropdown-menu">
          <li><a class="dropdown-item" href="/docs">Documentation</a></li>
          <li><a class="dropdown-item" href="/support">Support</a></li>
        </ul>
      </div>
    </div>
  </div>
</nav>

3. Create a collapsible content region

A collapse trigger points to the panel with data-bs-target. The selector must match the target’s ID. Give the target the .collapse class. For a trigger controlling one panel, include aria-controls and keep its initial aria-expanded value consistent with the panel’s initial state.

<button class="btn btn-primary" type="button"
        data-bs-toggle="collapse" data-bs-target="#details"
        aria-expanded="false" aria-controls="details">
  Show details
</button>

<div class="collapse" id="details">
  <div class="card card-body">
    Details go here.
  </div>
</div>

To start with the panel open, add show to the target and change the trigger’s initial aria-expanded to true:

<button class="btn btn-primary" type="button"
        data-bs-toggle="collapse" data-bs-target="#details"
        aria-expanded="true" aria-controls="details">
  Hide details
</button>

<div class="collapse show" id="details">
  <div class="card card-body">Details go here.</div>
</div>

Bootstrap changes the expanded state as the panel opens and closes. Put padding on an inner wrapper such as the card above, rather than directly on the animated .collapse element.

One trigger for multiple panels

A selector can target more than one collapse element. In that case, aria-controls is less useful because it is intended to identify a controlled element; prefer separate triggers when each panel needs an independently understandable control.

<button class="btn btn-primary" type="button"
        data-bs-toggle="collapse" data-bs-target=".more-details"
        aria-expanded="false">
  Toggle details
</button>
<div class="collapse more-details" id="detail-one">First panel</div>
<div class="collapse more-details" id="detail-two">Second panel</div>

4. Build an accordion-style group

Use data-bs-parent when opening one panel should close another panel in the same group. Each trigger still targets its own panel. This provides the coordinated show-and-hide behavior, but Bootstrap’s collapse plugin does not implement every optional keyboard interaction described by the ARIA Authoring Practices accordion pattern. If your interface needs that full interaction model, implement and test the missing keyboard behavior yourself.

<div id="faq-group">
  <h3>
    <button class="btn btn-link" type="button"
            data-bs-toggle="collapse" data-bs-target="#faq-one"
            aria-expanded="false" aria-controls="faq-one">
      What does this section do?
    </button>
  </h3>
  <div id="faq-one" class="collapse" data-bs-parent="#faq-group">
    <div class="p-3">It reveals one answer at a time.</div>
  </div>

  <h3>
    <button class="btn btn-link" type="button"
            data-bs-toggle="collapse" data-bs-target="#faq-two"
            aria-expanded="false" aria-controls="faq-two">
      Can another answer open?
    </button>
  </h3>
  <div id="faq-two" class="collapse" data-bs-parent="#faq-group">
    <div class="p-3">Yes. Opening it closes the other panel.</div>
  </div>
</div>

5. Initialize and control components with JavaScript

Data attributes are enough for the common click-to-toggle behavior. Use the JavaScript API when initialization or control must happen in your own code. Ensure the Bootstrap bundle is loaded before this code runs.

const dropdownElement = document.querySelector('.dropdown-toggle');
const dropdown = bootstrap.Dropdown.getOrCreateInstance(dropdownElement);
dropdown.show();
// dropdown.hide();
// dropdown.toggle();

const panelElement = document.querySelector('#details');
const panel = bootstrap.Collapse.getOrCreateInstance(panelElement, {
  toggle: false
});
panel.show();
// panel.hide();
// panel.toggle();

For a collapse component, toggle: false prevents initialization from immediately changing its state. Choose either data attributes or deliberate JavaScript control for a given interaction, and avoid attaching duplicate click handlers that toggle the same component twice.

6. Choose the right component and options

Need Use Key wiring
Show contextual links or actions Dropdown data-bs-toggle="dropdown" and .dropdown-menu
Reveal an arbitrary content region Collapse data-bs-toggle="collapse", a target selector, and .collapse
Allow only one panel in a group open Collapse with parent data-bs-parent="#group-id"

Dropdowns support placement and alignment classes such as .dropup, .dropend, .dropstart, and .dropdown-menu-end. Dynamic placement uses Popper outside navbars. For specialized cases, Bootstrap documents options including auto-close behavior and offset; use the version-specific documentation when setting these through data attributes or JavaScript.

Collapse’s core choices are its initial state, target selector, and optional parent grouping. The transition respects the user’s prefers-reduced-motion setting through Bootstrap’s styling. If the content is essential, ensure it remains available when JavaScript fails or provide an appropriate progressive-enhancement strategy for the application.

7. Accessibility and interaction details

  • Use a real button for a control that opens or closes content; provide visible text that describes its effect.
  • For a single collapse target, connect trigger and panel with matching aria-controls and target ID. Set aria-expanded to match the starting state.
  • Use links for navigation and buttons for actions inside dropdown menus. Choose ARIA roles based on the actual content and interaction; a dropdown is not automatically an application menu widget.
  • Bootstrap provides common dropdown keyboard behavior, including cursor-key movement among dropdown items and Escape to close. Check the behavior in the context of your page and do not assume Bootstrap supplies every interaction pattern for every menu type.
  • Do not make hover the only way to open a dropdown. Bootstrap’s documented dropdown interaction is click toggling.
  • Check focus visibility, contrast, and the reading order of the revealed content in your own theme.

8. Troubleshooting

Symptom Likely cause Fix
Clicking a dropdown does nothing Bootstrap JavaScript is missing, failed to load, or is the wrong version. Load the Bootstrap 5.3 JavaScript bundle and check the browser console and network panel for script errors.
Dropdown opens in the wrong place or is clipped Popper is missing where dynamic positioning is needed, or an ancestor’s overflow styles clip the menu. Use bootstrap.bundle outside navbar positioning cases and inspect ancestor positioning and overflow rules.
Bootstrap 5 markup does not respond The markup uses Bootstrap 4’s data-toggle attribute. Use Bootstrap 5’s data-bs-toggle and data-bs-target attributes.
Collapse trigger does nothing The target selector does not match the panel ID, or the panel lacks .collapse. Make the selector and ID identical, for example data-bs-target="#details" with id="details", and add the class.
Panel starts open but accessibility state says closed The target has .show but the trigger says aria-expanded="false". Set the initial state consistently: open means .show and aria-expanded="true".
Collapse animation jumps or behaves oddly Padding is applied to the animated .collapse element. Move padding to an inner wrapper.
Menu only works with a mouse hover A custom hover handler replaced or conflicts with the documented click toggle. Use Bootstrap’s click behavior and ensure the trigger is keyboard operable.
Component toggles twice or immediately closes Both Bootstrap’s data API and a custom click handler are toggling it, or duplicate scripts are loaded. Remove duplicate initialization and verify that only one handler controls the interaction.

9. Performance, reliability, and cost

Dropdowns and collapse panels are client-side UI components; their visible behavior depends on Bootstrap’s JavaScript being available and initialized. Keep the page to one compatible Bootstrap CSS and JavaScript version, and avoid unnecessary custom handlers. Collapse transitions animate the panel, so keep large or expensive work out of repeated click handlers.

The code in this guide uses the public jsDelivr CDN example. For production, follow your project’s asset policy, pin the framework version, and consider how assets are delivered and cached in your deployment. The components themselves do not require a paid service; costs depend on how your project hosts its assets and application.

10. Or skip the browser setup

If you need a screenshot of the finished dropdown or collapsible panel for a pull request, documentation page, or visual review, ScreenshotNeo can capture a URL with one GET request. See the ScreenshotNeo API documentation for parameters and formats.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners are accepted and removed before the shot; known consent platforms, newsletter popups, and chat widgets can be removed.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers say the page verdict and billing status.
  • An MCP server provides screenshot tools for AI agents, including Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

11. FAQ

Can a Bootstrap dropdown open on hover?

Bootstrap documents dropdowns as click-toggled. A custom hover interaction requires your own code and should preserve keyboard access.

Can a collapse panel start open?

Yes. Add show to the panel and initialize the trigger with aria-expanded="true".

Does a dropdown need Popper?

Popper is used for dynamic positioning outside navbars. Bootstrap’s bundle includes it, which is convenient when using dropdowns in those contexts.

Does collapse automatically create a fully accessible accordion?

No. data-bs-parent coordinates which panel is open, but Bootstrap does not include every optional keyboard interaction in the ARIA accordion pattern.