Few UI patterns are more universally useful than the accordion. Building a FAQ section, a sidebar navigation tree, a product detail panel, or a settings interface all depend on the same fundamental need: show and hide content on demand. 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.
This guide covers both components thoroughly: how they work, how to customise them, how to control them with JavaScript, and the common pitfalls that bite 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. That makes it straightforward to trigger side effects such as 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, so 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 to 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: Give multiple buttons the same data-bs-target value. Bootstrap handles state synchronisation automatically, keeping aria-expanded consistent across all of them.
For complex interactive UIs, a sidebar that mirrors a mobile menu toggle for instance, this shared-trigger pattern saves 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, which is 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. The result is a flat, edge-to-edge style that works well in sidebars or cards with tight padding.
<div class="accordion accordion-flush" id="sidebarAccordion">
<!-- accordion items here -->
</div>Always Open Accordion
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 on your content. Mutual-exclusivity suits FAQs where answers are alternatives to one another. Independent open panels suit checklists, settings panels, or step-by-step instructions where a user needs 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 where you need direct JavaScript control: dynamically generated content, SPA route changes, programmatic state resets. 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. This matters in practice: creating a second instance on the same element leads to duplicate event binding and unpredictable behaviour.
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 approach: no specificity battles, no !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, the guide on how to customise a Bootstrap 5 HTML template without breaking it sets out a systematic workflow.
Accessibility and Performance Best Practices
Bootstrap 5’s collapse and accordion components handle a lot of accessibility work for you. There are still 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 heading element (anything from h2 to h6) appropriate to the document outline. Screen readers rely on heading hierarchy to navigate content, and a div here will break that.
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 panels contain heavy images or iframes, use lazy-loading attributes and only initialise third-party widgets (such as 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, patch it 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
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.
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();
}
}
});Data attributes handle static, markup-driven interactions: they are processed once when the page loads. The JavaScript API gives you programmatic control at runtime. That distinction matters whenever collapse targets are created after the initial page render, or when you need to respond to application state changes rather than direct user clicks.
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.
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. 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: simple FAQ sections, complex multi-level navigation trees, and everything in between. All with minimal markup, no third-party dependencies, and solid accessibility out of the box. Understanding 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 confident Bootstrap users from those forever patching things after the fact.
These foundational Bootstrap primitives make you faster regardless of your starting point. The patterns 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.
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 and 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