Button Groups

A button group takes several individual .btn elements and visually welds them into one connected control — shared borders, no gaps between them, and rounded corners only on the two outer ends. It's the standard pattern for a set of mutually-related actions or filters, like a toolbar or a single-choice filter row.

1. Horizontal Button Groups: .btn-group

Wrap two or more buttons in a <div role="group"> with the .btn-group class. The role="group" attribute is required for assistive technology to announce the buttons as one related set.

<div class="btn-group" role="group" aria-label="Basic example">
  <button type="button" class="btn btn-outline-primary">Left</button>
  <button type="button" class="btn btn-outline-primary">Middle</button>
  <button type="button" class="btn btn-outline-primary">Right</button>
</div>

2. Vertical Button Groups: .btn-group-vertical

Stack the same buttons top-to-bottom instead of side-by-side by swapping the wrapper class.

<div class="btn-group-vertical" role="group" aria-label="Vertical button group">
  <button type="button" class="btn btn-secondary">Top</button>
  <button type="button" class="btn btn-secondary">Middle</button>
  <button type="button" class="btn btn-secondary">Bottom</button>
</div>

3. Sizing the Whole Group: .btn-group-lg

Instead of sizing every button individually, add .btn-group-lg or .btn-group-sm to the group wrapper once, and it cascades to every button inside.

<div class="btn-group btn-group-lg" role="group" aria-label="Large button group">
  <button type="button" class="btn btn-outline-dark">Left</button>
  <button type="button" class="btn btn-outline-dark">Right</button>
</div>

4. Nesting a Dropdown Inside a Group

A button group can contain a dropdown as one of its "buttons" by giving that button data-bs-toggle="dropdown" plus a sibling .dropdown-menu — the group still renders it as one seamless connected control.

<div class="btn-group" role="group">
  <button type="button" class="btn btn-primary">Sort by distance</button>

  <div class="btn-group" role="group">
    <button type="button" class="btn btn-primary dropdown-toggle"
      data-bs-toggle="dropdown" aria-expanded="false">
      More
    </button>
    <ul class="dropdown-menu">
      <li><a class="dropdown-item" href="#">Sort by rating</a></li>
      <li><a class="dropdown-item" href="#">Sort by name</a></li>
    </ul>
  </div>
</div>
Note: the dropdown's open/close behavior is handled by Bootstrap 5's own JavaScript bundle listening for data-bs-toggle="dropdown" — no jQuery, and no extra script needed beyond the Bootstrap 5 JS bundle. We cover dropdowns fully in a later lesson.

5. Worked Example: TrailMap Difficulty Filter

The trail listing page filters by difficulty using one connected button group. Clicking a button would normally toggle an active state via a small script (or a radio-styled group) to show which filter is currently selected — here Moderate is shown pre-selected using .active.

<div class="btn-group" role="group" aria-label="Filter by difficulty">
  <button type="button" class="btn btn-outline-success">Easy</button>
  <button type="button" class="btn btn-outline-warning active" aria-pressed="true">Moderate</button>
  <button type="button" class="btn btn-outline-danger">Difficult</button>
</div>
Design tip: each filter button borrows the same success/warning/danger keyword as its matching difficulty badge from the colors lesson — keeping the filter colors and the badge colors in sync helps users scan the page faster.
Next up: those difficulty colors show up again as small standalone labels — head to Badges for the distance and "New" tags on every trail card.