Zum Inhalt springen

Ein wenig JavaScript

Diese Schulung handelt von HTML und CSS. An einigen Stellen fehlt aber ein kleiner Anstoß: Ein Knopf soll ein Menü öffnen. Dafür genügt ein Muster, das du auch ohne JavaScript-Kenntnisse verwenden kannst.

  • ein Skript richtig einbinden
  • ein Element finden und auf einen Klick reagieren
  • eine Klasse umschalten, das Aussehen bleibt im CSS
  • den Zustand auch für Screenreader mitteilen

Live-Coding zum Mitmachen

⤓ demo-21-javascript.zip herunterladen

Der Ordner starter ist der Ausgangsstand, fertig der Stand nach dem Live-Coding.

Enthält: app.js, index.html, stil.css

Ein Knopf, eine Klasse
.inhalt { display: none; padding: 0.5rem; background: #e0e7ff; }
.inhalt.offen { display: block; }
<button id="knopf" type="button" aria-expanded="false" aria-controls="bereich">Mehr anzeigen</button>
<div class="inhalt" id="bereich">Jetzt bin ich sichtbar.</div>
<script>
const knopf = document.querySelector("#knopf");
const bereich = document.querySelector("#bereich");
knopf.addEventListener("click", () => {
const offen = bereich.classList.toggle("offen");
knopf.setAttribute("aria-expanded", offen);
});
</script>

Es besteht aus vier Teilen:

  1. Finden: document.querySelector nimmt denselben Selektor wie dein CSS.
  2. Reagieren: addEventListener("click", …) führt eine Funktion aus, sobald jemand klickt.
  3. Umschalten: classList.toggle setzt die Klasse oder nimmt sie weg und gibt zurück, ob sie jetzt gesetzt ist.
  4. Mitteilen: aria-expanded sagt dem Screenreader, ob der Bereich offen ist.

Das Aussehen steht weiterhin im CSS. Das Skript ändert nur einen Zustand. Dadurch bleibt beides getrennt, und die Gestaltung kannst du anpassen, ohne das Skript anzufassen.

<head>
<script src="app.js" defer></script>
</head>

defer führt das Skript erst aus, wenn das HTML fertig gelesen ist. Ohne defer findet querySelector die Elemente womöglich noch nicht. Fehler im Skript zeigt die Konsole in den DevTools: anders als CSS meldet JavaScript seine Fehler.

Bevor du zu JavaScript greifst, prüfe, ob es ohne geht:

Aufgabe Ohne JavaScript
Auf- und zuklappen details
Dialog schließen form method="dialog", Escape-Taste
Eingaben prüfen required, type, pattern
Auf Zustände reagieren :has(), :checked
Hover, Fokus CSS

Für das Öffnen eines Dialogs und ein umschaltbares Menü brauchen wir dagegen ein Skript.

Auf dem Handy nimmt das Menü zu viel Platz weg. Es soll hinter einem Knopf verschwinden und auf breiten Bildschirmen immer sichtbar sein. Der Dialog bekommt bei der Gelegenheit sein onclick aus dem HTML entfernt.

app.js
// Mobiles Menü: Das Skript ändert nur einen Zustand. Das Aussehen bleibt im CSS.
const menueKnopf = document.querySelector(".menue-knopf");
const menue = document.querySelector("#hauptmenue");
menueKnopf.addEventListener("click", () => {
const offen = menue.classList.toggle("offen");
menueKnopf.setAttribute("aria-expanded", offen);
});
// Der Dialog braucht kein onclick mehr im HTML
const dialog = document.querySelector("#neue-aufgabe");
document.querySelector(".filter .knopf").addEventListener("click", () => {
dialog.showModal();
});
stil.css
/* Ohne die Klasse „offen“ ist das Menü auf dem Handy zu */
@media (max-width: 47.99rem) {
.seitenleiste:not(.offen) {
display: none;
}
}

Die Media Query mit max-width sorgt dafür, dass die Klasse auf breiten Bildschirmen keine Rolle spielt.

Starter für die Übung

⤓ uebung-21-javascript.zip herunterladen

ZIP-Datei entpacken und den Ordner in VS Code öffnen (Datei → Ordner öffnen).

Enthält: app.js, index.html, stil.css, uebung.js

Schreibe deinen Code in uebung.js. Die Variablen menue, menueKnopf und dialog aus app.js kannst du weiterverwenden.

Ein offenes Menü schließt sich mit der Escape-Taste, und der Fokus kehrt auf den Knopf zurück. Tipp: keydown-Ereignis am document, ereignis.key === "Escape", und menueKnopf.focus().

Die Auswahl „Stufe“ blendet Karten aus. Reagiere auf change, gehe mit for…of über alle .karte und setze karte.hidden.

Beim Schließen des Dialogs entsteht eine neue Karte in der ersten Spalte. Tipp: document.createElement, textContent und append. Warum textContent und nie innerHTML für Eingaben von Nutzern?

Zeige im Titel jeder Spalte die Anzahl sichtbarer Karten an: JavaScript setzt ein data-anzahl-Attribut, und das CSS zeigt es mit attr() an. Oder baue einen Schalter für den Dunkelmodus, der sich die Wahl in localStorage merkt.