Modul 07 · Doppelstunde 4 · Finale

Mini-Projekt

Alles zusammen: HTML-Struktur, CSS-Styling, JavaScript-Interaktion — ihr baut eine interaktive Profilkarten-Seite von Grund auf.

Modul 01

Das Projekt

Ihr baut eine Seite mit interaktiven Profilkarten — wie ein kleines Team-Verzeichnis. Jede Karte zeigt einen Namen, eine Rolle, Skills, und einen Button, der mehr Infos aufklappt. Dafür nutzt ihr alles aus A1–A6.

A1–A2
HTML-Struktur
Tags, Attribute, Semantik
A3–A4
CSS-Styling
Selektoren, Boxmodell, Farben
A5
Layout
Flexbox, Grid, Responsive
A6
JavaScript
DOM, Events, classList
Modul 02

Schritt für Schritt

Folgt den 5 Schritten — kopiert den Code in den Editor unten, passt ihn an, und baut Stück für Stück eure eigene Version.

Schritt 1

HTML-Grundgerüst + Karten-Struktur

Erstellt die HTML-Basis mit einer Überschrift und einem Container für die Karten. Jede Karte bekommt Name, Rolle, Skills und einen versteckten Detail-Bereich.

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Unser Team</title>
</head>
<body>
  <h1>Unser <span class="highlight">Team</span></h1>
  <div class="karten-grid">

    <div class="karte">
      <h2>Max Mustermann</h2>
      <p class="rolle">Frontend-Entwickler</p>
      <div class="skills">
        <span>HTML</span> <span>CSS</span> <span>JS</span>
      </div>
      <button class="details-btn">Mehr erfahren</button>
      <div class="details">
        <p>Liebt sauberen Code und Pixel-perfektes Design.</p>
      </div>
    </div>

    <!-- Kopiert die Karte 2-3 Mal und ändert die Daten! -->

  </div>
</body>
</html>
Schritt 2

CSS: Basis-Styling

Fügt ein <style>-Tag im <head> ein. Setzt Schrift, Hintergrund, und stylt die Überschrift.

<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
  font-family: 'Segoe UI', sans-serif;
  background: #f5f5f5;
  padding: 2rem;
}
h1 {
  text-align: center;
  font-size: 2.5rem;
  margin-bottom: 2rem;
}
.highlight { color: #E63946; }
</style>
Schritt 3

CSS: Grid-Layout + Karten-Design

Die Karten werden per Grid angeordnet und bekommen Schatten, Rundungen und Hover-Effekte. Skills werden als farbige Badges dargestellt.

.karten-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
  max-width: 960px;
  margin: 0 auto;
}
.karte {
  background: #fff;
  border-radius: 12px;
  padding: 1.5rem;
  box-shadow: 0 2px 10px rgba(0,0,0,0.08);
  border-top: 4px solid #E63946;
  transition: transform 0.3s, box-shadow 0.3s;
}
.karte:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.rolle { color: #888; margin: 0.3rem 0 0.8rem; }
.skills span {
  display: inline-block;
  background: #1D3557;
  color: #fff;
  padding: 0.2rem 0.7rem;
  border-radius: 20px;
  font-size: 0.85rem;
  margin: 0.2rem;
}
.details { display: none; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid #eee; }
.details.open { display: block; }
Schritt 4

CSS: Button-Design

Der „Mehr erfahren"-Button bekommt ein professionelles Styling mit Hover-Effekt.

.details-btn {
  background: #2A9D8F;
  color: #fff;
  border: none;
  padding: 0.6rem 1.4rem;
  border-radius: 6px;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  margin-top: 1rem;
  transition: background 0.3s, transform 0.3s;
}
.details-btn:hover {
  background: #238b7e;
  transform: translateY(-2px);
}
Schritt 5

JavaScript: Interaktion

Per JavaScript hört jeder Button auf Klicks und togglet den Detail-Bereich. Fügt das <script> vor </body> ein.

<script>
// Alle Buttons finden
const buttons = document.querySelectorAll(".details-btn");

// Jedem Button einen Event-Listener geben
buttons.forEach(function(btn) {
  btn.addEventListener("click", function() {
    // Das .details-Div in derselben Karte finden
    const karte = btn.closest(".karte");
    const details = karte.querySelector(".details");

    // Klasse togglen
    details.classList.toggle("open");

    // Button-Text ändern
    if (details.classList.contains("open")) {
      btn.textContent = "Weniger zeigen";
    } else {
      btn.textContent = "Mehr erfahren";
    }
  });
});
</script>
Werkstatt

Live-Editor

Fügt den Code aus den Schritten zusammen, passt ihn an und klickt Ausführen. Eure Seite erscheint in der Vorschau.

Fortschritt

Projekt-Checkliste

Hakt ab, was ihr geschafft habt — so behaltet ihr den Überblick.

HTML-Grundgerüst mit <!DOCTYPE>, head und body
Mindestens 3 Profilkarten mit Name, Rolle, Skills
CSS-Reset und Basis-Styling (Schrift, Hintergrund)
Grid-Layout für die Karten (auto-fit + minmax)
Karten mit Schatten, Rundungen und Hover-Effekt
Skills als farbige Badges gestaltet
Button mit professionellem Styling
JavaScript: Details aufklappen per classList.toggle()
Button-Text ändert sich (Mehr/Weniger)
Eigene Anpassungen: Farben, Texte, Extras
0 / 10 erledigt
Bonus-Aufgaben

Selber coden

Vier Aufgaben, die ihr in eurem eigenen Projekt umsetzen könnt — egal ob Profilkarten, Portfolio, Rezeptseite oder etwas ganz anderes. Nutzt den Live-Editor oben zum Ausprobieren. Zu jeder Aufgabe gibt es Tipps, ein Code-Gerüst zum Ausfüllen und eine Musterlösung zum Aufdecken.

Aufgabe 1

Darkmode-Toggle

Füge deiner Seite einen Button hinzu, der zwischen hellem und dunklem Design umschaltet. Im Darkmode sollen Hintergrund und Textfarbe wechseln.

Du brauchst: classList.toggle() auf document.body, eine CSS-Klasse .dark mit neuen Farben, einen <button> mit addEventListener("click", ...)
/* CSS: */
.dark {
  /* ? */: #1a1a2e;
  /* ? */: #e0e0e0;
}
.dark .karte {
  background: /* ? */;
}

// JavaScript:
const btn = document.querySelector(/* ? */);
btn.addEventListener("click", function() {
  document.body./* ? */(/* ? */);
});
<!-- HTML: Button irgendwo auf der Seite einfügen -->
<button id="dark-toggle">🌙 Dunkelmodus</button>



/* CSS: Darkmode-Klasse auf body */
.dark {
  background: #1a1a2e;
  color: #e0e0e0;
}
.dark .karte {
  background: #2a2a4a;
  color: #e0e0e0;
  box-shadow: 0 2px 10px rgba(0,0,0,0.3);
}



// JavaScript:
const darkBtn = document.querySelector("#dark-toggle");

darkBtn.addEventListener("click", function() {
  document.body.classList.toggle("dark");

  // Button-Text anpassen:
  if (document.body.classList.contains("dark")) {
    darkBtn.textContent = "☀ Hellmodus";
  } else {
    darkBtn.textContent = "🌙 Dunkelmodus";
  }
});
Aufgabe 2

Live-Suchfeld

Baue ein Eingabefeld, das Elemente auf deiner Seite in Echtzeit filtert. Beim Tippen sollen nur die Elemente sichtbar bleiben, deren Text zum Suchbegriff passt.

Du brauchst: <input> mit addEventListener("input", ...), querySelectorAll() für die Elemente, textContent.toLowerCase().includes() zum Prüfen, style.display zum Ein-/Ausblenden
// Suchfeld und alle filterbaren Elemente finden:
const suchfeld = document.querySelector(/* ? */);
const elemente = document.querySelectorAll(/* ? */);

suchfeld.addEventListener(/* ? */, function() {
  const suchtext = suchfeld./* ? */.toLowerCase();

  elemente.forEach(function(el) {
    const inhalt = el./* ? */.toLowerCase();
    if (inhalt.includes(suchtext)) {
      el.style.display = /* ? */;
    } else {
      el.style.display = /* ? */;
    }
  });
});
<!-- HTML: Suchfeld über dem Inhaltsbereich einfügen -->
<input type="text" id="suchfeld" placeholder="Suchen...">

<!-- Die filterbaren Elemente brauchen eine gemeinsame Klasse: -->
<div class="karte">...</div>
<div class="karte">...</div>
<div class="karte">...</div>



// JavaScript:
const suchfeld = document.querySelector("#suchfeld");
const elemente = document.querySelectorAll(".karte");

suchfeld.addEventListener("input", function() {
  const suchtext = suchfeld.value.toLowerCase();

  elemente.forEach(function(el) {
    const inhalt = el.textContent.toLowerCase();
    if (inhalt.includes(suchtext)) {
      el.style.display = "";
    } else {
      el.style.display = "none";
    }
  });
});
Aufgabe 3

Element per Formular hinzufügen

Baue ein kleines Formular mit Eingabefeldern und einem „Hinzufügen"-Button. Beim Klick soll per JavaScript ein neues Element erstellt und in die Seite eingefügt werden — z.B. eine neue Karte, ein Listeneintrag oder ein Kommentar.

Du brauchst: <input>-Felder + <button>, document.createElement(), .textContent oder .innerHTML, appendChild() zum Einfügen, .value um den Eingabetext auszulesen
// Button und Container finden:
const addBtn = document.querySelector(/* ? */);
const container = document.querySelector(/* ? */);

addBtn.addEventListener("click", function() {
  // Werte aus den Eingabefeldern lesen:
  const titel = document.querySelector(/* ? */)./* ? */;

  // Neues Element erstellen:
  const neu = document./* ? */(/* ? */);
  neu.className = /* ? */;
  neu./* ? */ = titel;

  // In die Seite einfügen:
  container./* ? */(neu);
});
<!-- HTML: Formular über oder neben dem Inhaltsbereich -->
<div class="formular">
  <input type="text" id="input-name" placeholder="Name...">
  <input type="text" id="input-rolle" placeholder="Rolle...">
  <button id="hinzufuegen">+ Hinzufügen</button>
</div>

<!-- Der Container, in den neue Elemente eingefügt werden: -->
<div class="karten-grid">
  <!-- bestehende Karten ... -->
</div>



// JavaScript:
const addBtn = document.querySelector("#hinzufuegen");
const container = document.querySelector(".karten-grid");

addBtn.addEventListener("click", function() {
  // Werte aus den Eingabefeldern lesen:
  const titel = document.querySelector("#input-name").value;
  const rolle = document.querySelector("#input-rolle").value;

  // Prüfen ob Felder ausgefüllt sind:
  if (!titel || !rolle) { alert("Bitte beide Felder ausfüllen!"); return; }

  // Neues Element erstellen:
  const neu = document.createElement("div");
  neu.className = "karte";
  neu.innerHTML = `
    <h2>${titel}</h2>
    <p class="rolle">${rolle}</p>
  `
;

  // In die Seite einfügen:
  container.appendChild(neu);

  // Felder leeren:
  document.querySelector("#input-name").value = "";
  document.querySelector("#input-rolle").value = "";
});
Stretch

Einfacher Slider

Zeige mehrere Inhalte (Bilder, Karten, Zitate …) nacheinander an, steuerbar per Vor- und Zurück-Buttons. Immer nur ein Element ist sichtbar.

Du brauchst: Eine Index-Variable (let aktuell = 0), querySelectorAll() für alle Slider-Elemente, eine Funktion die alle auf display: none setzt und nur das aktuelle auf display: block, zwei Buttons mit addEventListener("click", ...) die den Index erhöhen/verringern
// Alle Slides und Buttons finden:
const slides = document.querySelectorAll(/* ? */);
let aktuell = /* ? */;

function zeigen() {
  slides.forEach(s => s.style.display = /* ? */);
  slides[aktuell].style.display = /* ? */;
}

document.querySelector("#vor").addEventListener("click", function() {
  aktuell = (aktuell + 1) % /* ? */;
  /* ? */();
});

document.querySelector("#zurueck").addEventListener("click", function() {
  aktuell = (aktuell - 1 + slides.length) % /* ? */;
  /* ? */();
});

/* ? */(); // Beim Laden erstes Slide zeigen
<!-- HTML: Slider-Container mit Buttons und Slides -->
<div class="slider">
  <button id="zurueck">← Zurück</button>
  <button id="vor">Weiter →</button>
</div>

<!-- Jeder Slide bekommt die gleiche Klasse: -->
<div class="slide">Inhalt 1 (Text, Bild, Karte …)</div>
<div class="slide">Inhalt 2</div>
<div class="slide">Inhalt 3</div>



// JavaScript:
const slides = document.querySelectorAll(".slide");
let aktuell = 0;

function zeigen() {
  slides.forEach(s => s.style.display = "none");
  slides[aktuell].style.display = "block";
}

document.querySelector("#vor").addEventListener("click", function() {
  aktuell = (aktuell + 1) % slides.length;
  zeigen();
});

document.querySelector("#zurueck").addEventListener("click", function() {
  aktuell = (aktuell - 1 + slides.length) % slides.length;
  zeigen();
});

zeigen(); // Beim Laden erstes Slide zeigen
Interaktive Aufgabe

Sortieraufgabe: Debugging

Euer Button funktioniert nicht. In welcher Reihenfolge geht ihr beim Debugging vor?

Fix anwenden und erneut testen
Konsole öffnen (F12) und Fehlermeldung lesen
Problem identifizieren: Was genau funktioniert nicht?
Ergebnis prüfen und Code committen
Fehlerquelle lokalisieren: Welche Zeile? Welcher Selektor?

Quiz: Gesamtwissen

7 Fragen quer durch A1–A7 — das Finale.

Nachschlagen

Glossar Flip-Karten

Die wichtigsten Begriffe der gesamten Serie — klicke zum Aufdecken.

Semantisches HTML klicken HTML-Tags, die ihre Bedeutung beschreiben: <header>, <nav>, <main>, <article>, <section>, <footer>.
CSS Grid klicken Zweidimensionales Layout-System. Definiert Zeilen und Spalten gleichzeitig. Ideal für Seiten-Layouts und Kartenraster.
classList.toggle() klicken JavaScript-Methode: Fügt eine CSS-Klasse hinzu, wenn sie fehlt — entfernt sie, wenn sie da ist. Perfekter Schalter für UI-Effekte.
box-sizing: border-box klicken CSS-Eigenschaft, die Padding und Border in die Gesamtbreite einrechnet. Verhindert, dass Elemente größer werden als erwartet.
closest() klicken DOM-Methode: Sucht vom aktuellen Element aufwärts im Baum nach dem nächsten Vorfahren, der zum Selektor passt.
auto-fit + minmax() klicken Grid-Muster für responsive Layouts ohne Media Queries: repeat(auto-fit, minmax(250px, 1fr)) erstellt so viele Spalten wie passen.

Diskussion

„Präsentiert euer Projekt der Gruppe. Was war die größte Herausforderung? Welches Konzept aus A1–A7 war am nützlichsten? Und: Was würdet ihr als Nächstes lernen wollen — Animationen, APIs, ein eigenes Backend?"