Building a tabbed component
Tabs (Tabbys) zeigen und verbergen Inhalte – wie Registerkarten im Browser, nur innerhalb der Seite.
Das HTML
Section titled “Das HTML”Ein Tabby besteht aus zwei Komponenten:
- aus den Tabs
- aus den Inhalten der jeweiligen Tabs
Wir starten mit folgendem HTML:
<div class="tabby"> <div class="tabs"> <button class="tab">Tab 1</button> <button class="tab">Tab 2</button> <button class="tab">Tab 3</button> </div> <div class="tabs-content"> <section class="tab-content">Content section 1</section> <section class="tab-content">Content section 2</section> <section class="tab-content">Content section 3</section> </div></div>Da ein Tab (und sein zugehöriger Inhalt) immer geöffnet sein müssen, vergeben wir gleich die Klasse is-selected an den ersten Tab und den ersten Inhalt:
<div class="tabby"> <div class="tabs"> <button class="tab is-selected">Tab 1</button> <button class="tab">Tab 2</button> <button class="tab">Tab 3</button> </div> <div class="tabs-content"> <section class="tab-content is-selected">Content section 1</section> <section class="tab-content">Content section 2</section> <section class="tab-content">Content section 3</section> </div></div>Styling tabs (and their tab content)
Section titled “Styling tabs (and their tab content)”Ein geöffneter Tab muss sich optisch deutlich von den geschlossenen Tabs abheben. Dafür verwenden wir hier filter:
// closed tabs are de-emphasized.tab { filter: grayscale(75%) brightness(0.9);}
// emphasize the selected tab.tab.is-selected { filter: none; background-color: white;}Wenn ein Tab ausgewählt ist, soll der zugehörige Inhalt angezeigt und die anderen Tabs versteckt werden. Wir machen das mit display: none.
// hide tab-content when not selected.tab-content { display: none;}
// show selected tab-content.tab-content.is-selected { display: block;}Switching Tabs
Section titled “Switching Tabs”Wenn ein Tab ausgewählt wird, müssen folgende Dinge passieren:
- die Klasse
is-selectedmuss vom aktuell angezeigten Tab entfernt werden - die Klasse
is-selectedmuss vom aktuell angezeigten Tab-Content entfernt werden - die Klasse
is-selectedmuss dem ausgewählten Tab zugewiesen werden - die Klasse
is-selectedmuss dem Inhalt des ausgewählten Tabs zugewiesen werden
<div class="tabby"> <div class="tabs"> <button class="tab">Tab 1</button> <button class="tab is-selected">Tab 2</button> <button class="tab">Tab 3</button> </div> <div class="tabs-content"> <section class="tab-content">Content section 1</section> <section class="tab-content is-selected">Content section 2</section> <section class="tab-content">Content section 3</section> </div></div>Switching Tabs with JavaScript
Section titled “Switching Tabs with JavaScript”Wenn der User einen Tab anklickt, muss dieser ausgewählt werden. Folgende Schritte müssen wir mit JavaScript machen:
- einen EventListener für die Tabs hinzufügen
- den geklickten Tab finden
- den zugehörigen Tab-Content identifizieren
is-selectedvon allen Tabs entfernenis-selectedvon allen Tab-Inhalten entfernenis-selecteddem angeklickten Tab zuweisenis-selecteddem zugehörigen Inhalt zuweisen
Adding event listeners
Section titled “Adding event listeners”Wir verwenden querySelectorAll, um alle Tabs auszuwählen. Dann loopen wir mit forEach durch die einzelnen Tabs und verwenden addEventListener, um einen EventListener für jeden Tab hinzuzufügen.
const tabs = Array.from(document.querySelectorAll('.tab'));
tabs.forEach(tab => { tab.addEventListener('click', e => { // do sth. });});Finding the clicked tab
Section titled “Finding the clicked tab”Wenn ein Event feuert, feuert es auf dem Tab, der geklickt wurde. Das können wir loggen:
tabs.forEach(tab => { tab.addEventListener('click', e => { console.log(tab); });});Finding the correct tab content
Section titled “Finding the correct tab content”Nun müssen wir noch den zugehörigen Tab-Content identifizieren. Dafür gibt es zwei Möglichkeiten:
- Elemente zählen
- Ein Zielelement festlegen
Für Tabby macht ein Zielelement mehr Sinn, weil jedes Tab seinen ihm zugeordneten Tab-Content hat (wie man zählt, schauen wir uns im Carousel an).
Um ein Zielelement festzulegen, machen wir zwei Dinge:
- Wir geben dem Tab-Content eine
idmit einem bestimmten Wert - Wir geben dem Tab ein Attribut (z.B.
data-target), das denselben (einzigartigen) Wert enthält wie dieiddes zugehörigen Inhalts.
Das funktioniert, weil es keine zwei Elemente mit derselbenidgeben darf.
<div class="tabby"> <div class="tabs"> <button class="tab is-selected" data-target="content-1">Tab 1</button> <button class="tab" data-target="content-2">Tab 2</button> <button class="tab" data-target="content-3">Tab 3</button> </div> <div class="tabs-content"> <section id="content-1" class="tab-content is-selected">Content section 1</section> <section id="content-2" class="tab-content">Content section 2</section> <section id="content-3" class="tab-content">Content section 3</section> </div></div>Damit können wir herauslesen, welches Tab der User geklickt hat …
tabs.forEach(tab => { tab.addEventListener('click', e => { const target = tab.dataset.target; console.log(target); });});… und in weiterer Folge bestimmen, welcher Tab-Content dazugehört:
tabs.forEach(tab => { tab.addEventListener('click', e => { const target = tab.dataset.target; const tabContent = tabby.querySelector('#' + target); console.log(tabContent); });});Selecting a tab
Section titled “Selecting a tab”Um den geklickten Tab nun sichtbar zu machen, müssen wir nur noch die Klassen richtig setzen.
is-selectedvom aktuell aktiven Tab entfernen (wir loopen einfach über alle Tabs)is-selecteddem angeklickten Tab zuweisen
tabs.forEach(tab => { tab.addEventListener('click', e => { // ... tabs.forEach(t => t.classList.remove('is-selected')); tab.classList.add('is-selected'); });});Wir nutzen hier eine neue Variable t, weil wir tab nicht überschreiben wollen.
Selecting a tab-content
Section titled “Selecting a tab-content”Um den zugehörigen Tab-Content auszuwählen, verwenden wir denselben Ansatz, also über alle Tab-Contents drüberloopen und die is-selected Klasse entfernen und dem ausgewählten Tab-Content wieder hinzufügen:
const tabContents = Array.from(tabby.querySelectorAll('.tab-content'));
tabs.forEach(tab => { tab.addEventListener('click', e => { // ... tabContents.forEach(c => c.classList.remove('is-selected')); tabContent.classList.add('is-selected'); });});