Skip to content

Building an Accordion

Accordeons sind Komponenten, die Bereiche mit Informationen anzeigen oder verstecken können. Wenn das Accordeon geschlossen ist, sehen wir nur den Accordeon-Header. Wenn das Accordeon geöffnet ist, sehen wir den Inhalt des Accordeons.

Wir wollen Header und Inhalt eines Accordeons sauber bündeln. Deshalb wrappen wir beide in ein umschließendes <div>.

<div class="accordion">
<div class="accordion-header">...</div>
<div class="accordion-content">...</div>
</div>

Wenn die Seite geladen wird, soll das Accordeon geschlossen sein. Wir müssen also den Content verstecken und das tun wir mit display: none.

.accordion-content {
display: none;
}

Um das Accordeon zu öffnen, klicken wir auf den Header. Dazu sollten wir diesen in ein <button> Element einpacken (wir erinnern uns: Buttons geben uns die Funktionalität mit, die wir brauchen: wir können mit der Tastatur einen Klick triggern).

Wir möchten den Accordeon-Header stylen, dazu verwenden wir ein Überschrift-Element, z.B. <h2>. Da wir eine Überschrift nicht innerhalb eines Buttons verwenden dürfen, umgekehrt jedoch schon, wrappen wir den Button in die Überschrift:

<header class="accordion-header">
<h2>
<button>
<span class="accordion-title">Accordion 1</span>
<div class="accordion-indicator">...</div>
</button>
</h2>
</header>

Um das Accordeon zu öffnen, geben wir dem umschließenden <div> die Klasse is-open mit. Wenn is-open vorhanden ist, setzen wir einen neuen Wert für display.

<!-- opened accordion -->
<div class="accordion is-open">...</div>
// opens the accordion
.accordion.is-open .accordion-content {
display: block; // or grid or flex ...
}

… wie wir es bei der OCN und beim Modal gemacht haben?
Weil die Klasse nicht auf <body> angewendet wird, sondern auf .accordion und das ist dann eh schon eindeutig …

Die Indikatoren zeigen uns, was passiert, wenn wir drauf klicken:

  1. wenn wir auf + klicken, öffnet sich das Accordeon
  2. wenn wir auf - klicken, schließt sich das Accordeon

Wenn das Accordeon geschlossen ist, müssen wir das + anzeigen und das - verstecken. Wenn das Accordeon geöffnet ist, genau umgekehrt.

// geschlossen
.indicator-plus {
display: block;
.is-open & {
display: none;
}
}
// geöffnet
.indicator-minus {
display: none;
.is-open & {
display: block;
}
}

Opening the first accordion with JavaScript

Section titled “Opening the first accordion with JavaScript”

Wenn der User auf den ersten Accordeon-Header klickt, wollen wir den Inhalt des ersten Accordeons anzeigen. Wir lauschen daher auf ein Klick-Event:

const firstAccordion = document.querySelector('.accordion');
const firstAccordionHeader = firstAccordion.querySelector('.accordion-header');
firstAccordionHeader.addEventListener('click', e => {
firstAccordion.classList.toggle('is-open');
});

Gut, das war mal eines. Wir wollen eventuell alle Accordions öffnen. Also machen wir weiter …

// select all accordions with querySelectorAll
const accordions = document.querySelectorAll('.accordion');
// find the accordions
const firstAccordion = accordions[0];
const secondAccordion = accordions[1];
...
// find headers for the respective accordions
const firstAccordionHeader = firstAccordion.querySelector('.accordion-header');
const secondAccordionHeader = secondAccordion.querySelector('.accordion-header');
...
// add event listeners to the accordion headers
firstAccordionHeader.addEventListener('click', e => {
firstAccordion.classList.toggle('is-open');
});
secondAccordionHeader.addEventListener('click', e => {
secondAccordion.classList.toggle('is-open');
});
...

Wir haben jetzt drei Dinge vier mal gemacht:

  1. Ein Accordeon ausgewählt
  2. den zugehörigen Accordeon-Header gefunden
  3. einen EventListener auf den Header gelegt

Das ist natürlich sehr unelegant. Wir machen das jetzt mit einer forEach Scheife. Um forEach verwenden zu können, sollten wir sicherheitshalber aus der NodeList einen Array machen.

const accordions = Array.from(document.querySelectorAll('.accordion'));
accordions.forEach(accordion => {
// find the accordion header
const accordionHeader = accordion.querySelector('.accordion-header');
// add an event listener to the accordion header
accordionHeader.addEventListener('click', e => {
// toggle the is-open class
accordion.classList.toggle('is-open');
});
});