Accordion
Sample:
Frequently asked questions
First question
First answer…
Second question
Second answer…
Code:
<style>
.faq [aria-expanded] {
all: unset;
cursor: pointer;
}
.faq [aria-expanded]:focus-visible {
outline: 4px solid;
}
h3:has([aria-expanded="false"]) + .faq-content {
display: none;
}
</style>
<section aria-labelledby="faq_heading" class="faq">
<h2 id="faq_heading">
Frequently asked questions
</h2>
<h3>
First question
</h3>
<div class="faq-content">
<p>
First answer…
</p>
</div>
<h3>
Second question
</h3>
<div class="faq-content">
<p>
Second answer…
</p>
</div>
<!--
repeat for as many accordion panels as needed
-->
</section>
<script>
const faq = document.querySelector(' .faq')
const headings = faq.querySelectorAll('h3')
for (let i = 0; i < headings.length; i++) {
const button = document.createElement('button')
const heading = headings[i]
const content = heading.nextElementSibling
const id = `faq_${i}`;
button.setAttribute('aria-expanded', false)
button.setAttribute('aria-controls', id)
button.textContent = heading.textContent
heading.innerHTML = ''
heading.append(button)
content.setAttribute('id', id)
}
faq.addEventListener('click', e => {
const button = e.target.closest('[aria-expanded]')
const isOpen = button.getAttribute('aria-expanded') === "false"
if (button) {
button.setAttribute('aria-expanded', isOpen)
}
})
</script>