Bootstrap 5 Accordion and Collapse: Everything You Need to Know
Few UI patterns are more universally useful than the accordion. Whether you are building a FAQ section, a sidebar navigation tree, a product detail panel, or a settings interface, the ability to show and hide content on demand is fundamental to good user experience. Bootstrap 5 ships with two closely related components that handle exactly this: the collapse component and the accordion component. They share the same JavaScript engine under the hood, but serve distinct use cases.
In this guide, you will get a thorough understanding of both components — how they work, how to customise them, how to control them with JavaScript, and how to avoid the common pitfalls that trip up developers working with Bootstrap 5 for the first time. Every concept comes with real, copy-paste-ready code you can drop straight into a project or into a premium HTML template like Canvas Template.
Key Takeaways
Key Takeaways
- Bootstrap 5 Collapse is a general-purpose show/hide component driven by data attributes or JavaScript.
- Bootstrap 5 Accordion is a structured wrapper around Collapse that enforces single-panel-open behaviour by default.
- Both components are fully accessible and keyboard-navigable out of the box.
- You can control open/close behaviour, animate height transitions, and trigger multiple targets without writing a single line of JavaScript.
- Custom SCSS variables let you restyle accordions to match any brand without touching the core Bootstrap source.
- The
always-openaccordion variant removes the mutual-exclusivity restriction when you need multiple panels open simultaneously.
How the Bootstrap 5 Collapse Component Works
The collapse component is the foundation. At its simplest, it connects a trigger element (a button or anchor) to a target element via a shared ID or data-bs-target attribute. When the trigger is activated, Bootstrap toggles the show class on the target and animates its height from zero to its natural height using a CSS transition.
The component fires four JavaScript events you can hook into: show.bs.collapse, shown.bs.collapse, hide.bs.collapse, and hidden.bs.collapse. This makes it easy to trigger side effects — updating icons, loading remote content, or logging analytics events — without fighting the framework.
The bare minimum markup looks like this:
<!-- Trigger -->
<button
class="btn btn-primary"
type="button"
data-bs-toggle="collapse"
data-bs-target="#myCollapsePanel"
aria-expanded="false"
aria-controls="myCollapsePanel"
>
Toggle Panel
</button>
<!-- Target -->
<div class="collapse" id="myCollapsePanel">
<div class="card card-body">
This content is hidden by default and revealed on click.
</div>
</div>Two things to note: first, the aria-expanded attribute is toggled automatically by Bootstrap — you do not need to manage it manually. Second, if you want the panel to start open, add the show class to the target element alongside collapse.
Multiple Targets and Shared Triggers
One less-discussed feature of the Bootstrap collapse component is its ability to target multiple elements from a single trigger, or share a single target across multiple triggers.
One trigger, many targets: Pass a CSS selector string to data-bs-target that matches multiple elements.
<button
class="btn btn-secondary"
type="button"
data-bs-toggle="collapse"
data-bs-target=".multi-collapse"
aria-expanded="false"
>
Toggle All Panels
</button>
<div class="collapse multi-collapse" id="panelA">
<div class="card card-body">Panel A content</div>
</div>
<div class="collapse multi-collapse" id="panelB">
<div class="card card-body">Panel B content</div>
</div>Many triggers, one target: Simply give multiple buttons the same data-bs-target value. Bootstrap handles the state synchronisation automatically, keeping aria-expanded consistent across all of them.
If you are building complex interactive UIs — for instance, a sidebar that mirrors a mobile menu toggle — this shared-trigger pattern saves you a lot of custom JavaScript. It pairs particularly well with the layout techniques covered in our guide on building a landing page with Bootstrap 5 in under an hour.
Building a Bootstrap 5 Accordion From Scratch
The accordion component is essentially a styled group of collapse panels with a parent-awareness mechanism. When one panel opens, the others close — unless you opt out of that behaviour. Here is the full structural markup:
<div class="accordion" id="faqAccordion">
<!-- Item 1 -->
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button
class="accordion-button"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseOne"
aria-expanded="true"
aria-controls="collapseOne"
>
What is Bootstrap 5?
</button>
</h2>
<div
id="collapseOne"
class="accordion-collapse collapse show"
aria-labelledby="headingOne"
data-bs-parent="#faqAccordion"
>
<div class="accordion-body">
Bootstrap 5 is the most popular open-source CSS framework for
building responsive, mobile-first websites.
</div>
</div>
</div>
<!-- Item 2 -->
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseTwo"
aria-expanded="false"
aria-controls="collapseTwo"
>
Does Bootstrap 5 require jQuery?
</button>
</h2>
<div
id="collapseTwo"
class="accordion-collapse collapse"
aria-labelledby="headingTwo"
data-bs-parent="#faqAccordion"
>
<div class="accordion-body">
No. Bootstrap 5 dropped the jQuery dependency entirely.
It ships with its own vanilla JavaScript plugins.
</div>
</div>
</div>
<!-- Item 3 -->
<div class="accordion-item">
<h2 class="accordion-header" id="headingThree">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseThree"
aria-expanded="false"
aria-controls="collapseThree"
>
Can I use Bootstrap 5 with SCSS?
</button>
</h2>
<div
id="collapseThree"
class="accordion-collapse collapse"
aria-labelledby="headingThree"
data-bs-parent="#faqAccordion"
>
<div class="accordion-body">
Absolutely. Bootstrap 5 ships full SCSS source files so you can
override variables and extend styles at build time.
</div>
</div>
</div>
</div>The critical linking mechanism is data-bs-parent="#faqAccordion" on each collapse panel. This tells Bootstrap to close all sibling panels within the parent when any panel opens. Remove this attribute and all panels become independent — the “always open” variant discussed next.
Accordion Variants: Flush Style and Always Open
Bootstrap 5 ships two first-class accordion variants out of the box, controlled purely by class modifiers.
Flush Accordion
Add accordion-flush to the wrapper to remove the outer border and rounded corners, producing a flat, edge-to-edge style ideal for sidebars or cards with tight padding.
<div class="accordion accordion-flush" id="sidebarAccordion">
<!-- accordion items here -->
</div>Always Open Accordion
Simply omit the data-bs-parent attribute from every panel. Each panel then operates as an independent collapse, and multiple panels can be open simultaneously.
<div class="accordion" id="alwaysOpenAccordion">
<div class="accordion-item">
<h2 class="accordion-header" id="aoHeadingOne">
<button
class="accordion-button"
type="button"
data-bs-toggle="collapse"
data-bs-target="#aoCollapseOne"
aria-expanded="true"
aria-controls="aoCollapseOne"
>
Section 1 (stays open independently)
</button>
</h2>
<div id="aoCollapseOne" class="accordion-collapse collapse show">
<div class="accordion-body">Content for section 1.</div>
</div>
</div>
</div>Choosing between the two depends entirely on your content. Mutual-exclusivity works well for FAQs where answers are alternatives. Independent open panels work better for checklists, settings panels, or step-by-step instructions where a user may need to reference multiple sections at once.
Collapse vs Accordion: Choosing the Right Component
The table below summarises the key differences to help you choose the right tool for each situation.
| Feature | Bootstrap Collapse | Bootstrap Accordion |
|---|---|---|
| Mutual exclusivity | No (panels are independent) | Yes (via data-bs-parent) |
| Structural requirements | Minimal — any trigger + target | Requires .accordion, .accordion-item, .accordion-header, .accordion-body |
| Built-in styling | None (bring your own) | Full: borders, chevron icon, padding, colours |
| Best for | Custom UI patterns, toggleable sections, mobile menus | FAQs, documentation trees, settings panels |
| Multiple triggers per panel | Yes | Yes |
| JavaScript API | Collapse class |
Collapse class (same engine) |
| ARIA management | Automatic | Automatic |
Controlling Collapse and Accordion With JavaScript
Data attributes get you far, but there are scenarios — dynamically generated content, SPA route changes, programmatic state resets — where you need direct JavaScript control. Bootstrap 5 exposes a clean class-based API for exactly this.
// Get or create an instance
const collapseEl = document.getElementById('myCollapsePanel');
const bsCollapse = new bootstrap.Collapse(collapseEl, {
toggle: false // prevent auto-toggle on instantiation
});
// Programmatic control
bsCollapse.show();
bsCollapse.hide();
bsCollapse.toggle();
// Listen to events
collapseEl.addEventListener('shown.bs.collapse', () => {
console.log('Panel is fully open');
});
collapseEl.addEventListener('hidden.bs.collapse', () => {
console.log('Panel is fully closed');
});You can also retrieve an existing instance rather than creating a new one, which is important to avoid duplicate event binding:
const existingInstance = bootstrap.Collapse.getInstance(collapseEl);
if (existingInstance) {
existingInstance.hide();
}A common real-world pattern is collapsing all accordion panels at once — for example, when a “Reset” button is clicked in a settings page:
document.getElementById('resetAllBtn').addEventListener('click', () => {
document.querySelectorAll('.accordion-collapse.show').forEach(panel => {
bootstrap.Collapse.getInstance(panel)?.hide();
});
});Customising the Accordion With SCSS
Bootstrap 5’s accordion ships with a set of dedicated SCSS variables. Overriding them at the variable layer — before the Bootstrap source compiles — is the cleanest way to customise without specificity battles or !important hacks. This is the same philosophy covered in depth in our post on using SCSS variables to theme a Bootstrap 5 site.
The most useful accordion variables to know:
// _variables-override.scss
// Place this file before @import "bootstrap"
$accordion-bg: #ffffff;
$accordion-border-color: rgba(0, 0, 0, 0.1);
$accordion-border-radius: 0.5rem;
$accordion-inner-border-radius: 0.4rem;
$accordion-body-padding-x: 1.5rem;
$accordion-body-padding-y: 1.25rem;
$accordion-button-bg: #f8f9fa;
$accordion-button-active-bg: #e9ecef;
$accordion-button-active-color: #0d6efd;
$accordion-button-focus-border-color: #86b7fe;
$accordion-icon-color: #212529;
$accordion-icon-active-color: #0d6efd;
$accordion-transition: color 0.15s ease-in-out,
background-color 0.15s ease-in-out,
border-color 0.15s ease-in-out,
box-shadow 0.15s ease-in-out,
border-radius 0.15s ease;If you want to replace the default chevron icon with a custom SVG (a plus/minus pattern is popular), override the icon variables using inline SVG encoded as a data URI:
$accordion-button-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M8 2v12M2 8h12'/%3e%3c/svg%3e");
$accordion-button-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%230d6efd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 8h12'/%3e%3c/svg%3e");This technique is exactly what Canvas Template uses internally — the accordion components across its 40+ pre-built pages are all driven by SCSS variable overrides, making it trivial to reskin every accordion on the site by changing a handful of values. If you find yourself doing a lot of this kind of work, also check our guide on how to customise a Bootstrap 5 HTML template without breaking it for a systematic workflow.
Accessibility and Performance Best Practices
Bootstrap 5’s collapse and accordion components are designed with accessibility in mind, but there are a few things you need to get right in your own markup.
Use semantic heading elements inside accordion headers. The .accordion-header class should wrap an actual h2–h6 element appropriate to the document outline. Screen readers rely on heading hierarchy to navigate content.
Always include aria-controls on triggers pointing to the ID of the panel they control. Bootstrap manages aria-expanded automatically, but aria-controls must be set in your HTML.
Avoid nesting accordions deeply. While technically possible, deeply nested accordions create both accessibility challenges (complex focus management) and visual confusion. Flat structures almost always serve users better.
For performance with many panels, be aware that all accordion content exists in the DOM from initial load. If you have panels containing heavy images or iframes, use lazy-loading attributes and only initialise third-party widgets (like carousels or maps) inside the shown.bs.collapse event callback rather than at page load. This is the same principle used in the Bootstrap 5 card components guide when dealing with media-rich card grids.
Disable transitions on reduced-motion preference: Bootstrap respects the prefers-reduced-motion media query natively via its $enable-transitions and $enable-reduced-motion SCSS variables. If you are using the compiled CSS CDN version, you can patch this with a single CSS override:
@media (prefers-reduced-motion: reduce) {
.accordion-collapse {
transition: none !important;
}
}This small addition meaningfully improves the experience for users with vestibular disorders or motion sensitivity.
Frequently Asked Questions
Can I use the Bootstrap 5 accordion without Bootstrap’s full CSS?
Yes, but it requires some work. The accordion depends on CSS custom properties and a handful of utility classes (collapse, show) as well as the specific .accordion-* rules. You can extract the relevant SCSS partials (_accordion.scss and _transitions.scss) and compile only those, along with the collapse JavaScript plugin. This is viable for performance-critical projects but adds maintenance overhead when Bootstrap updates.
How do I open a specific accordion panel on page load based on a URL hash?
Listen to the DOMContentLoaded event, read window.location.hash, and programmatically call .show() on the matching panel using the JavaScript API. Make sure the panel’s ID matches the hash fragment, and add the show class to the first panel only as a default fallback when no hash is present.
document.addEventListener('DOMContentLoaded', () => {
const hash = window.location.hash;
if (hash) {
const targetPanel = document.querySelector(hash + '.accordion-collapse');
if (targetPanel) {
new bootstrap.Collapse(targetPanel, { toggle: false }).show();
}
}
});What is the difference between data-bs-toggle="collapse" and the JavaScript API?
Data attributes handle static, markup-driven interactions — they are processed once when the page loads. The JavaScript API gives you programmatic control at runtime, which is essential for dynamic UIs where collapse targets may be created after the initial page render, or where you need to respond to application state changes rather than user clicks.
Why does my accordion jump or flash when animating?
The most common cause is placing content with a fixed height or explicit padding directly inside the .collapse wrapper rather than inside an inner element. Bootstrap calculates height from the natural content height of the collapsible element, and if that element has additional CSS transitions applied, they can conflict. Always put your content inside .accordion-body (for accordions) or a plain inner div (for raw collapse), and avoid applying height, max-height, or overflow transitions to the .collapse element itself.
Can I use Bootstrap 5 accordion inside a Bootstrap modal?
Yes, with one caveat: the data-bs-parent attribute creates a parent-child relationship based on DOM containment. As long as your accordion wrapper is inside the modal body, it will work correctly. Just ensure your accordion and modal IDs are unique across the page, since Bootstrap uses getElementById internally. If you dynamically inject accordion markup into a modal, initialise the collapse instances manually using the JavaScript API after the shown.bs.modal event fires.
The Bootstrap 5 accordion and collapse components are deceptively powerful. They cover the vast majority of interactive content-reveal patterns you will encounter in real projects — from simple FAQ sections to complex multi-level navigation trees — with minimal markup, no third-party dependencies, and solid accessibility out of the box. Mastering the relationship between the data-attribute API and the JavaScript API, and knowing when to reach for SCSS variables rather than overriding compiled CSS, is what separates template consumers from template masters.
In 2026, as component-driven development continues to mature, understanding these foundational Bootstrap primitives makes you significantly faster regardless of whether you are starting from a blank file or customising a premium template. The patterns you have learned here apply equally whether you are hand-coding every line or using a tool like CanvasBuilder — the AI website builder that generates Bootstrap 5 HTML you can own and deploy anywhere — to scaffold the initial structure.
Ready to Build Faster?
Canvas Template gives you 40+ beautifully crafted Bootstrap 5 pages — including fully styled accordion and collapse patterns — ready to drop into any project. Stop building from scratch.
Skip the setup — build it free
Spin up a complete Bootstrap 5 site, blog included, with Canvas Builder. No coding, no cost.
Canvas Team
Tutorials and tips for building beautiful Bootstrap 5 websites with the Canvas HTML Template and Canvas Builder.
More from the Canvas Blog