How To Create an Accordion
Learn how to build an accordion: a list of questions where each one opens to show its answer.
Step 1: The HTML
Each item has a button (the question) followed by a panel (the answer).
Example
<button class="acc">What are the class timings?</button>
<div class="acc-panel"><p>Morning and evening batches, Monday to Friday.</p></div>
<button class="acc">Can I join online?</button>
<div class="acc-panel"><p>Yes, every course is also offered online.</p></div>Step 2: The CSS
The panels start with max-height: 0 and overflow: hidden, so they are closed. A transition makes the height change smoothly. The ::after part adds a plus sign that becomes a minus when open.
Example
.acc { width: 100%; text-align: left; padding: 14px; border: none; background: #ecfdf5; cursor: pointer; font-size: 16px; }
.acc::after { content: "+"; float: right; font-weight: bold; }
.acc.open::after { content: "-"; }
.acc-panel { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; padding: 0 14px; }Step 3: The JavaScript
When a question is clicked, toggle its open class. Then set the panel's max-height to its real content height (scrollHeight) to open it, or back to 0 to close it.
Example
document.querySelectorAll(".acc").forEach(function (btn) {
btn.addEventListener("click", function () {
btn.classList.toggle("open");
const panel = btn.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
});nextElementSibling is the element right after the button: its answer panel.
The Complete Example
Example
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 20px; max-width: 600px; }
.acc { width: 100%; text-align: left; padding: 14px; margin-top: 6px; border: none; border-radius: 6px; background: #ecfdf5; color: #065f46; cursor: pointer; font-size: 16px; }
.acc:hover { background: #d1fae5; }
.acc::after { content: "+"; float: right; font-weight: bold; }
.acc.open::after { content: "-"; }
.acc-panel { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; padding: 0 14px; }
</style>
</head>
<body>
<h2>Frequently Asked Questions</h2>
<button class="acc">What are the class timings?</button>
<div class="acc-panel"><p>We have morning and evening batches, Monday to Friday, and a weekend batch.</p></div>
<button class="acc">Can I join online?</button>
<div class="acc-panel"><p>Yes. Every course is offered online with live classes and recordings.</p></div>
<button class="acc">Do I get a certificate?</button>
<div class="acc-panel"><p>Yes, you get a certificate after you finish the course project.</p></div>
<script>
document.querySelectorAll(".acc").forEach(function (btn) {
btn.addEventListener("click", function () {
btn.classList.toggle("open");
const panel = btn.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
});
</script>
</body>
</html>Try it Yourself »Why max-height and Not display?
| Method | Animation |
|---|---|
display: none / block | No; it jumps open instantly |
max-height: 0 to a value | Yes; CSS can smoothly animate the height |
HTML also has a built-in accordion: the <details> and <summary> elements open and close with no JavaScript at all. It is a great choice for simple FAQs.
Example
<details>
<summary>Is there a fee for the free tutorials?</summary>
<p>No, all tutorials on this site are free.</p>
</details>Exercise
Exercise
In the script, what does btn.nextElementSibling return?
