Collapse & Accordion
Long pages are easier to read when details stay hidden until the reader asks for them: a "Read more" section, a list of filters, frequently asked questions. Bootstrap's collapse plugin shows and hides any element with a smooth animation, and the accordion component uses it to build a stack of panels where opening one closes the others.
In this lesson you will toggle content with collapse, control panels from JavaScript, and build an FAQ accordion with all its accessibility attributes.
Basic collapse
A collapse needs a target element with the collapse class (which hides it) and a trigger that points at it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Collapse</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4" style="max-width: 620px">
<h1 class="h4">Ganga Aarti boat tour, Varanasi</h1>
<p>A one-hour evening boat ride along the ghats to watch the aarti from the river.</p>
<button class="btn btn-outline-primary btn-sm" type="button" data-bs-toggle="collapse"
data-bs-target="#tourDetails" aria-expanded="false" aria-controls="tourDetails">
Show details
</button>
<div class="collapse mt-3" id="tourDetails">
<div class="card card-body">
Starts at 6 pm from Dashashwamedh Ghat. Price ₹450 per adult, ₹200 for children under 10.
Life jackets provided.
</div>
</div>
<hr class="my-4">
<p class="mb-2">Control two panels with one button, or each on its own:</p>
<div class="d-flex gap-2 mb-3">
<button class="btn btn-secondary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target=".day-plan"
aria-expanded="false" aria-controls="day1 day2">Toggle both days</button>
<button class="btn btn-outline-secondary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#day1"
aria-expanded="false" aria-controls="day1">Day 1</button>
<button class="btn btn-outline-secondary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#day2"
aria-expanded="false" aria-controls="day2">Day 2</button>
</div>
<div class="row g-3">
<div class="col-sm-6"><div class="collapse day-plan" id="day1"><div class="card card-body">Day 1: Kashi Vishwanath, ghats walk, evening aarti.</div></div></div>
<div class="col-sm-6"><div class="collapse day-plan" id="day2"><div class="card card-body">Day 2: Sarnath, silk weavers' market, return.</div></div></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>How collapse works:
collapsehides the element.collapse showmakes it visible from the start.- The trigger has
data-bs-toggle="collapse"anddata-bs-target, which is a CSS selector.#tourDetailstargets one element;.day-plantargets every element with that class, so one button can toggle several panels. - While animating, Bootstrap swaps
collapseforcollapsing, which animates the height. Avoid padding or margin on the.collapseelement itself, because it makes the animation jump. Put the padding on an inner element, as the examples do withcard card-body. aria-expandedtells screen readers whether the content is open, and Bootstrap updates it.aria-controlsnames the element (or elements, separated by spaces) that the button controls.
A link can be a trigger too: <a href="#tourDetails" data-bs-toggle="collapse" role="button">. A button is still the better choice, because the action happens on this page.
For a sideways slide, add collapse-horizontal to the collapse element and give its child a fixed width. It animates the width instead of the height.
Controlling collapse from JavaScript
const panel = document.getElementById("tourDetails");
const details = bootstrap.Collapse.getOrCreateInstance(panel, { toggle: false });
details.show();
details.hide();
details.toggle();
panel.addEventListener("shown.bs.collapse", () => {
console.log("Details are now visible");
});Pass { toggle: false } when creating the instance. By default, creating a Collapse instance also toggles it once, which surprises many people. The events are show.bs.collapse, shown.bs.collapse, hide.bs.collapse and hidden.bs.collapse.
Accordion
An accordion is a stack of collapsible panels with headers. It is the standard way to show FAQs. Each panel is an accordion-item with a header button and a collapsing body:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FAQ accordion</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4" style="max-width: 680px">
<h1 class="h4 mb-3">Admission FAQ: Kochi Public School</h1>
<div class="accordion" id="faq">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#faq1"
aria-expanded="true" aria-controls="faq1">
When do admissions open?
</button>
</h2>
<div id="faq1" class="accordion-collapse collapse show" data-bs-parent="#faq">
<div class="accordion-body">Forms are available from 1 December to 15 January at the school office and online.</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="#faq2"
aria-expanded="false" aria-controls="faq2">
What documents are needed?
</button>
</h2>
<div id="faq2" class="accordion-collapse collapse" data-bs-parent="#faq">
<div class="accordion-body">Birth certificate, address proof, two photos and the previous school's report card.</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="#faq3"
aria-expanded="false" aria-controls="faq3">
Is there a school bus?
</button>
</h2>
<div id="faq3" class="accordion-collapse collapse" data-bs-parent="#faq">
<div class="accordion-body">Yes. Buses cover Edappally, Kakkanad and Vyttila. The fee depends on distance.</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>The important attributes:
- The open panel has
collapse show, and its button hasaria-expanded="true"withoutcollapsed. Closed panels havecollapseonly, and their buttons have thecollapsedclass (which turns the arrow) andaria-expanded="false". Keep these matched in your HTML; Bootstrap keeps them in sync after the first click. data-bs-parent="#faq"on each panel is what makes it an accordion: opening one panel closes the others inside the same parent.- The button sits inside a heading (
<h2 class="accordion-header">), so screen-reader users can jump between questions with heading shortcuts. Pick the heading level that fits your page outline.
Two variations:
- Always open: remove
data-bs-parentfrom the panels, and several can be open at once. - Flush: add
accordion-flushto theaccordionto remove the outer borders and rounded corners, so it sits edge to edge inside a card or sidebar.
The native alternative: details and summary
HTML's own <details> and <summary> elements also show and hide content, with no JavaScript at all, and giving several <details> the same name attribute makes them behave like an accordion. You can style them with Bootstrap utilities:
<details class="border rounded p-3 mb-2" name="faq">
<summary class="fw-semibold">Is there a uniform shop?</summary>
<p class="mt-2 mb-0">Yes, inside the campus, open 9 am to 1 pm.</p>
</details>Bootstrap 5.3's accordion uses its JavaScript plugin, but the Bootstrap 6 alpha rebuilds the accordion on <details> and <summary>. For a simple FAQ, the native elements are a good choice today; see Details & Dialog.
Common mistakes
- Padding on the
.collapseelement. The animation jumps at the end. Put padding on a child element. - Forgetting
collapsedon closed accordion buttons. The arrows point the wrong way until the first click. data-bs-parentpointing at the wrong element. Panels no longer close each other. It must match the accordion's id.new bootstrap.Collapse(el)without{ toggle: false }. The panel toggles the moment the instance is created.
Key points
collapsehides an element; a trigger withdata-bs-toggle="collapse"anddata-bs-targetshows and hides it.data-bs-targetis a selector, so a class can control several panels at once.- Keep
aria-expandedandaria-controlson triggers; avoid padding on the collapsing element itself. - An accordion is
accordion > accordion-item > accordion-header + accordion-collapse;data-bs-parentmakes only one panel open at a time. accordion-flushremoves outer borders, and<details name>is a no-JavaScript alternative for simple cases.
Exercise
Build a "Fee structure" accordion for a Jaipur college with three panels: Tuition, Hostel and Transport, each with one sentence and an amount in rupees. Use the flush style and the always-open behaviour, and start with every panel closed. Above it, add a "Show all fees" button that toggles all three panels at once by targeting a class they share.
Show solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fee structure</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4" style="max-width: 620px">
<button class="btn btn-primary btn-sm mb-3" type="button" data-bs-toggle="collapse" data-bs-target=".fee-panel"
aria-expanded="false" aria-controls="tuition hostel transport">Show all fees</button>
<div class="accordion accordion-flush border rounded" id="fees">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#tuition" aria-expanded="false" aria-controls="tuition">Tuition</button>
</h2>
<div id="tuition" class="accordion-collapse collapse fee-panel">
<div class="accordion-body">₹48,000 per year, payable in two instalments.</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="#hostel" aria-expanded="false" aria-controls="hostel">Hostel</button>
</h2>
<div id="hostel" class="accordion-collapse collapse fee-panel">
<div class="accordion-body">₹6,500 per month including meals.</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="#transport" aria-expanded="false" aria-controls="transport">Transport</button>
</h2>
<div id="transport" class="accordion-collapse collapse fee-panel">
<div class="accordion-body">₹1,200 per month for routes inside Jaipur city.</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>All buttons start with collapsed and every panel with plain collapse, so everything begins closed. The panels share the class fee-panel, so the top button's data-bs-target=".fee-panel" toggles all three. The panels have no data-bs-parent, which is what makes the accordion always-open.
Quick Quiz
1. Which class makes a collapse element visible when the page loads?
show is the visible state of a collapse; Bootstrap adds and removes it when toggling.
2. What makes accordion panels close each other when one opens?
Panels with the same data-bs-parent act as a group where only one is open.
3. Why should you avoid padding directly on a .collapse element?
The collapse animation measures height, and padding on the element itself makes it jerky.
4. What does { toggle: false } do in bootstrap.Collapse.getOrCreateInstance(el, { toggle: false })?
By default a new Collapse instance toggles once on creation; toggle: false prevents that.
Learn Bootstrap with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
