Accordion

An accordion is a stack of Collapse panels styled and grouped together — each panel has its own always-visible header button, and clicking one expands its body. It's the natural fit for a TrailMap FAQ section, which is exactly what we'll build below.

Anatomy of an Accordion

ClassRole
.accordionThe outer wrapper for the whole group of panels.
.accordion-itemOne question/answer pair — header plus its collapsible body.
.accordion-headerWraps the clickable button; renders as an <h2> by convention for accessibility.
.accordion-buttonThe actual clickable trigger, styled with a rotating chevron icon.
.accordion-collapseThe hideable panel — this is a .collapse element (see the previous lesson).
.accordion-bodyPadding wrapper for the panel's actual content.
<div class="accordion" id="trailFaq">
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button" type="button"
        data-bs-toggle="collapse" data-bs-target="#faqPermits">
        Do I need a permit?
      </button>
    </h2>
    <div id="faqPermits" class="accordion-collapse collapse show" data-bs-parent="#trailFaq">
      <div class="accordion-body">
        Some trails require a day permit, shown on each trail's detail page.
      </div>
    </div>
  </div>
</div>
Note: the trigger still uses data-bs-toggle="collapse", not some separate "accordion" toggle value — an accordion button is just a styled Collapse trigger.

data-bs-parent: Keeping Only One Panel Open

Add data-bs-parent="#trailFaq" (pointing at the outer .accordion element's id) to every .accordion-collapse panel in the group, and opening one panel automatically closes whichever one was open before — the classic FAQ behavior where only one answer shows at a time.

Omitting data-bs-parent: Multiple Panels Open at Once

Leave data-bs-parent off every panel and each one behaves as an independent Collapse — opening one has no effect on the others, so a user can have several panels expanded simultaneously. Bootstrap 5 doesn't have a separate "always-multi-open" class; it's purely whether data-bs-parent is present.

Note: a common mistake is adding data-bs-parent to only some panels in a group — the ones without it will happily stay open while others close, so keep it consistent across every .accordion-collapse in a given accordion.

Worked Example: TrailMap FAQ Accordion

TrailMap's help page answers three common questions, one panel open by default:

<div class="accordion" id="trailFaq">

  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button" type="button"
        data-bs-toggle="collapse" data-bs-target="#faqPermits"
        aria-expanded="true" aria-controls="faqPermits">
        Do I need a permit for these trails?
      </button>
    </h2>
    <div id="faqPermits" class="accordion-collapse collapse show" data-bs-parent="#trailFaq">
      <div class="accordion-body">
        Some trails require a day permit, shown right on each trail's detail page.
      </div>
    </div>
  </div>

  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button"
        data-bs-toggle="collapse" data-bs-target="#faqDogs"
        aria-expanded="false" aria-controls="faqDogs">
        Are dogs allowed?
      </button>
    </h2>
    <div id="faqDogs" class="accordion-collapse collapse" data-bs-parent="#trailFaq">
      <div class="accordion-body">
        Leashed dogs are welcome on most trails; check the individual trail page for exceptions.
      </div>
    </div>
  </div>

  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button"
        data-bs-toggle="collapse" data-bs-target="#faqAccount"
        aria-expanded="false" aria-controls="faqAccount">
        Do I need an account to submit a trail?
      </button>
    </h2>
    <div id="faqAccount" class="accordion-collapse collapse" data-bs-parent="#trailFaq">
      <div class="accordion-body">
        Yes — a free account lets us attribute the write-up to you and notify you of edits.
      </div>
    </div>
  </div>

</div>

Notice the closed buttons carry an extra .collapsed class and aria-expanded="false" to match their starting state — Bootstrap's JS keeps both in sync after the first click, but the initial markup needs to be correct by hand.

Note: want every panel independently toggleable instead? Just delete the three data-bs-parent="#trailFaq" attributes — nothing else in the markup changes.

The Flush Variant

Add .accordion-flush on the outer .accordion element to remove the default borders and rounded corners, useful when the accordion sits flush inside another bordered container (like a sidebar card):

<div class="accordion accordion-flush" id="trailFaq"> ... </div>
Next: Head to Carousel to cycle through a set of trail photos.