mitmario.dev

Klassen schalten

JavaScript Im Browser 3 Min Lesezeit 3 BeispieleLektion 3 von 9

Ein Element sieht anders aus, weil es eine Klasse trägt. Das ist die Arbeitsteilung, auf der jede gepflegte Seite steht: das Aussehen steht im Stylesheet, JavaScript sagt nur, welcher Zustand gerade gilt.

Vier Methoden an classList

add, remove und contains
const karte = document.getElementById("karte");

karte.classList.add("ist-aktiv");
console.log("nach add:", karte.className);

// Mehrere auf einmal gehen auch.
karte.classList.add("gross", "hervor");
console.log("nach add:", karte.className);

// Eine Klasse zweimal hinzuzufügen ändert nichts.
karte.classList.add("gross");
console.log("immer noch:", karte.className);

karte.classList.remove("hervor");
console.log("nach remove:", karte.className);

// Eine Klasse zu entfernen, die gar nicht da ist, ist erlaubt
// und tut nichts. Es gibt keinen Fehler dafür.
karte.classList.remove("gibt-es-nicht");

console.log("aktiv?", karte.classList.contains("ist-aktiv"));
console.log("Anzahl:", karte.classList.length);

classList ist eine Liste der Klassen des Elements, und sie bringt alles mit, was man mit Klassen tun will.

add("ist-aktiv") fügt hinzu. Mehrere Namen in einem Aufruf sind erlaubt, und eine Klasse doppelt hinzuzufügen ändert nichts: sie ist danach genau einmal da.

remove("hervor") nimmt weg. Eine Klasse zu entfernen, die gar nicht da ist, ist ausdrücklich erlaubt und tut einfach nichts. Du musst also nicht vorher fragen.

contains("ist-aktiv") fragt und liefert true oder false. Das kennst du aus Lektion 10.5.

toggle("offen") schaltet um, und das ist der interessante Fall.

toggle, und warum das zweite Argument zählt

toggle mit und ohne zweites Argument
const eins = document.getElementById("eins");
const zwei = document.getElementById("zwei");

// Ohne zweites Argument: an, wenn aus, und aus, wenn an.
console.log(eins.classList.toggle("offen"), eins.className);
console.log(eins.classList.toggle("offen"), eins.className);
console.log(eins.classList.toggle("offen"), eins.className);

// Mit zweitem Argument: setze auf genau diesen Zustand.
// Egal wie oft, das Ergebnis ist immer dasselbe.
const istAngemeldet = true;
zwei.classList.toggle("sichtbar", istAngemeldet);
zwei.classList.toggle("sichtbar", istAngemeldet);
console.log("zwei:", zwei.className);

// Das hier ist dieselbe Aussage in vier Zeilen.
if (istAngemeldet) {
  zwei.classList.add("sichtbar");
} else {
  zwei.classList.remove("sichtbar");
}

Ohne zweites Argument macht toggle das, was der Name sagt: ist die Klasse da, kommt sie weg, ist sie weg, kommt sie hin. Zurück gibt es true, wenn die Klasse danach da ist. Für einen Knopf, der ein Menü auf- und zuklappt, ist das genau richtig.

Den Rückgabewert siehst du am besten in der Eingabezeile der Console. Am Ende des Beispiels trägt eins die Klasse, dreimal umgeschaltet heißt einmal an. eins.classList.toggle("offen") antwortet dort false, noch einmal getippt true: jede Eingabe schaltet um. eins.classList.toggle("offen", false) antwortet false, und noch einmal getippt wieder false, denn mit zweitem Argument wird nichts umgeschaltet, sondern gesetzt.

Mit zweitem Argument ist es etwas ganz anderes. toggle("sichtbar", istAngemeldet) heißt: setze die Klasse auf genau diesen Zustand. Ist der Wert true, ist die Klasse danach da, ist er false, ist sie weg. Wie oft du die Zeile ausführst, spielt keine Rolle.

Unten im Beispiel steht dieselbe Aussage noch einmal ausgeschrieben: vier Zeilen mit if, add, else, remove. Die stehen in jedem Projekt hundertfach herum, und sie haben einen Nachteil, der über die Länge hinausgeht: es sind zwei Stellen, an denen der Klassenname steht. Wer eine davon umbenennt und die andere vergisst, bekommt einen Zustand, der sich anschalten, aber nicht mehr abschalten lässt.

Merksatz: Sobald du eine Bedingung hast, nimm toggle mit zweitem Argument. Umschalten ohne Bedingung ist der Fall für toggle ohne zweites.

Warum nicht className

Was className anrichtet
const mitListe = document.getElementById("mit-liste");
const mitText = document.getElementById("mit-text");

// classList.add ergänzt.
mitListe.classList.add("ist-aktiv");
console.log("classList:", mitListe.className);

// className = überschreibt alles. Die drei Klassen aus dem
// Markup sind weg, und mit ihnen ihr Aussehen.
mitText.className = "ist-aktiv";
console.log("className:", mitText.className);

// Der beliebte Versuch, das zu retten, geht auch schief:
// ein fehlendes Leerzeichen macht aus zwei Klassen eine.
mitText.className = mitText.className + "gross";
console.log("und jetzt:", mitText.className);
console.log("ist gross dabei?", mitText.classList.contains("gross"));

className ist der ganze Klassen-Text am Stück. Beim Lesen ist das gelegentlich praktisch. Beim Schreiben ist es fast immer falsch.

mitText.className = "ist-aktiv" setzt nicht eine Klasse, es ersetzt alle. Die drei Klassen aus dem Markup sind danach weg, und damit auch alles, was das Stylesheet an ihnen festgemacht hat.

Das siehst du im Beispiel nebeneinander. Die obere Karte behält Rahmen, Schatten und Schriftgröße und bekommt die Färbung dazu. Die untere steht danach nackt da, nur mit dem hellen Grund aus ist-aktiv: Rahmen und Größe hingen an karte und gross, und die hat eine einzige Zuweisung weggewischt. Der Fehler fällt oft erst auf, wenn jemand später eine Klasse im Markup ergänzt und sie plötzlich verschwindet.

Der übliche Rettungsversuch macht es nicht besser: className = className + "gross" hängt an, ohne Leerzeichen. Im Beispiel steht danach ist-aktivgross da, eine einzige Klasse mit diesem Namen. Die gibt es nirgends, contains("gross") sagt false, und im Stylesheet greift keine Regel. mitText.classList in der Eingabezeile der Console zeigt es als Liste: DOMTokenList {0: "ist-aktivgross"}, ein Eintrag. mitListe.classList daneben hat vier.

In diesem Kurs kommt className = deshalb nicht mehr vor. classList kann alles davon, ohne dabei etwas kaputtzumachen.

Klasse oder style

Das ist die Frage der nächsten Lektion, hier schon die kurze Antwort: Wenn du den Wert vorher kennst, gehört er ins Stylesheet und wird über eine Klasse geschaltet. Ein ist-versteckt, ein hat-fehler, ein ist-aktiv: das sind Zustände, ihr Aussehen ist eine Entscheidung des Designs und keine des Programms.

Erst wenn ein Wert zur Laufzeit entsteht und im Stylesheet gar nicht stehen kann, ist style an der Reihe. Wie das aussieht, zeigt Lektion 11.4.

Zum Mitnehmen

toggle mit zweitem Argument ersetzt jedes if (x) add() else remove(). Es ist eine Zeile statt vier und kann nicht auseinanderlaufen.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.