diff --git a/lessons/de/00-basic-selectors.json b/lessons/de/00-basic-selectors.json
new file mode 100644
index 0000000..096be6f
--- /dev/null
+++ b/lessons/de/00-basic-selectors.json
@@ -0,0 +1,550 @@
+{
+ "$schema": "../../schemas/code-crispies-module-schema.json",
+ "id": "css-basic-selectors",
+ "title": "CSS: Grundlegende Selektoren",
+ "description": "CSS-Selektoren sind die Grundlage für das Stylen von Webseiten und ermöglichen es dir, bestimmte HTML-Elemente für die Gestaltung auszuwählen. Dieses Modul stellt grundlegende Selektortypen vor, einschließlich Element-Typ-Selektoren, Klassen-Selektoren, ID-Selektoren und des universellen Selektors.",
+ "difficulty": "beginner",
+ "lessons": [
+ {
+ "id": "introduction-to-selectors",
+ "title": "Was ist ein CSS-Selektor?",
+ "description": "Ein CSS-Selektor ist der erste Teil einer CSS-Regel, der dem Browser mitteilt, welche HTML-Elemente die im Deklarationsblock definierten Stile erhalten sollen. Selektoren sind im Wesentlichen Muster, die mit Elementen in deinem HTML-Dokument übereinstimmen. Das Verstehen von Selektoren ist grundlegend, da sie bestimmen, welche Elemente von deinen CSS-Regeln betroffen sind. Das Element oder die Elemente, die von einem Selektor anvisiert werden, werden als 'Subjekt des Selektors' bezeichnet. Beim Schreiben einer CSS-Regel gibst du zuerst den Selektor an, gefolgt von geschweiften Klammern, die die Stil-Deklarationen enthalten. Um beispielsweise die Textfarbe von Elementen zu ändern, kannst du die color-Eigenschaft in deinem Deklarationsblock verwenden.
/* Element-Selektor */\np {\n color: orangered;\n /* │ └─── Gibt den Wert des Ausdrucks an\n │ \n └─────────── Gibt die Eigenschaft des Ausdrucks an */\n}
",
+ "task": "Schreibe eine CSS-Regel mit einem Typ-Selektor, die alle Absatz-Elemente p im Dokument anvisiert. Mache den Text blau, indem du die color-Eigenschaft auf blue setzt.",
+ "previewHTML": "
Einführung in CSS-Selektoren
\n
Dieser Absatz sollte blau werden.
\n
Dieses div-Element sollte unverändert bleiben.
\n
Dieser zweite Absatz sollte ebenfalls blau werden.
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; }",
+ "sandboxCSS": "h1, p, div { padding: 8px; margin-bottom: 10px; border: 1px dashed #ccc; }",
+ "codePrefix": "/* Schreibe einen Typ-Selektor, um alle Absatz-Elemente anzuvisieren */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "p { color: blue }",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^p\\s*{",
+ "message": "Beginne deine Regel mit p { … }, um alle Absatz-Elemente auszuwählen",
+ "options": {
+ "caseSensitive": false
+ }
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color:-Eigenschaft in deine CSS-Regel ein"
+ },
+ {
+ "type": "contains",
+ "value": "blue",
+ "message": "Setze den Farbwert auf blue"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "blue"
+ },
+ "message": "Verwende color: blue, um die Textfarbe zu setzen"
+ },
+ {
+ "type": "regex",
+ "value": "p\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": false
+ }
+ }
+ ]
+ },
+ {
+ "id": "type-selectors",
+ "title": "Typ-Selektoren: HTML-Elemente anvisieren",
+ "description": "Typ-Selektoren (auch Tag-Name-Selektoren oder Element-Selektoren genannt) visieren HTML-Elemente basierend auf ihrem Tag-Namen an. Zum Beispiel wählt p alle Absatz-Elemente, h1 alle Überschriften der ersten Ebene und div alle Division-Elemente aus. Typ-Selektoren sind die grundlegendste Art, Elemente auszuwählen, und wenden Stile einheitlich auf alle Instanzen eines bestimmten HTML-Elements in deinem Dokument an. Du kannst verschiedene CSS-Eigenschaften mit Typ-Selektoren definieren, wie color für Textfarbe, background-color für den Hintergrund und font-weight für Textbetonung. Sie bieten einen breiten Ansatz für das Styling deiner Seite und sind oft der Ausgangspunkt für spezifischeres Styling mit anderen Selektortypen.",
+ "task": "Schreibe drei separate CSS-Regeln mit Typ-Selektoren, um bestimmte HTML-Elemente anzuvisieren: mache h2-Überschriften purple, gib span-Elementen einen yellow-Hintergrund und mache strong-Elemente red.",
+ "previewHTML": "
Typ-Selektoren Beispiel
\n
Normaler Absatztext mit einem hervorgehobenen Span, der einen gelben Hintergrund haben sollte.
\n
Ein weiterer Absatz mit wichtigem, fetten Text, der rot sein sollte.
\n
Eine weitere Überschrift
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; }",
+ "sandboxCSS": "h2, p, span, strong { padding: 3px; }",
+ "codePrefix": "/* Schreibe drei separate Typ-Selektoren unten */\n\n",
+ "initialCode": "/* 1. Mache h2-Überschriften lila */\n\n\n/* 2. Gib span-Elementen einen gelben Hintergrund */\n\n\n/* 3. Mache strong-Elemente rot */\n",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "/* 1. Mache h2-Überschriften lila */\nh2 {\n color: purple;\n}\n\n/* 2. Gib span-Elementen einen gelben Hintergrund */\nspan {\n background-color: yellow;\n}\n\n/* 3. Mache strong-Elemente rot */\nstrong {\n color: red;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^h2\\s*{",
+ "message": "Füge einen h2 { … }-Selektor hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "purple"
+ },
+ "message": "Setze die color-Eigenschaft auf purple für h2-Elemente"
+ },
+ {
+ "type": "regex",
+ "value": "h2\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine h2-Regel mit einer schließenden Klammer } zu beenden"
+ },
+ {
+ "type": "regex",
+ "value": "^span\\s*{",
+ "message": "Füge einen span { … }-Selektor hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "yellow"
+ },
+ "message": "Setze background-color: yellow für span-Elemente"
+ },
+ {
+ "type": "regex",
+ "value": "span\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine span-Regel mit einer schließenden Klammer } zu beenden"
+ },
+ {
+ "type": "regex",
+ "value": "^strong\\s*{",
+ "message": "Füge einen strong { … }-Selektor hinzu"
+ },
+ {
+ "type": "regex",
+ "value": "strong\\s*{\\s*color:\\s*red;[^}]*}",
+ "message": "Setze color: red für strong-Elemente"
+ }
+ ]
+ },
+ {
+ "id": "class-selectors",
+ "title": "Klassen-Selektoren: Elementgruppen stylen",
+ "description": "Klassen-Selektoren visieren Elemente mit einem bestimmten Klassen-Attributwert an. Sie beginnen mit einem Punkt (.) gefolgt vom Klassennamen. Klassen sind mächtig, weil sie es ermöglichen, die gleichen Stile auf mehrere Elemente anzuwenden, unabhängig von ihrem Typ. Ein HTML-Element kann mehrere Klassen haben (durch Leerzeichen im class-Attribut getrennt), und eine Klasse kann auf beliebig viele Elemente angewendet werden. Bei der Verwendung von Klassen-Selektoren kannst du Eigenschaften wie background-color zum Setzen der Hintergrundfarbe und font-weight zur Kontrolle der Textdicke anwenden. Diese Flexibilität macht Klassen-Selektoren zu einer der am häufigsten verwendeten Methoden zur Anwendung von Stilen in CSS und ermöglicht modulares und wiederverwendbares Styling auf deiner gesamten Website.",
+ "task": "Erstelle eine CSS-Regel mit einem Klassen-Selektor, die Elemente mit der Klasse highlight anvisiert. Gib diesen Elementen einen yellow-Hintergrund und bold-Text.",
+ "previewHTML": "
Verwendung von Klassen-Selektoren
\n
Dies ist ein normaler Absatz, aber dieser Span hat die highlight-Klasse angewendet.
\n
Dieser gesamte Absatz hat die highlight-Klasse.
\n
\n
Normales Listenelement
\n
Dieses Listenelement ist hervorgehoben
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; }",
+ "sandboxCSS": "h2, p, li { padding: 5px; margin-bottom: 10px; }",
+ "codePrefix": "/* Erstelle einen Klassen-Selektor für Elemente mit der 'highlight'-Klasse */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^\\.highlight\\s*{",
+ "message": "Beginne deine Regel mit .highlight { … }, um einen Klassen-Selektor zu erstellen",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "background-color:",
+ "message": "Füge die background-color:-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "yellow"
+ },
+ "message": "Setze die Hintergrundfarbe auf yellow"
+ },
+ {
+ "type": "contains",
+ "value": "font-weight:",
+ "message": "Füge die font-weight:-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "font-weight",
+ "expected": "bold"
+ },
+ "message": "Setze font-weight auf bold"
+ },
+ {
+ "type": "regex",
+ "value": "\\.highlight\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "multiple-classes",
+ "title": "Mit mehreren Klassen arbeiten",
+ "description": "HTML-Elemente können mehrere Klassen gleichzeitig haben, was komponierbare und modulare CSS-Designs ermöglicht. Wenn ein Element mehrere Klassen hat, erhält es Stile von allen passenden Klassen-Selektoren. Dieser Ansatz ermöglicht es dir, eine Bibliothek wiederverwendbarer CSS-Klassen aufzubauen, die auf verschiedene Arten kombiniert werden können. Du kannst auch Elemente anvisieren, die eine bestimmte Kombination von Klassen haben, indem du Klassen-Selektoren ohne Leerzeichen verkettst (z.B. .class1.class2). Beim Stylen dieser Elemente könntest du Eigenschaften wie border-color verwenden, um die Farbe von Element-Rahmen zu ändern, und background-color, um die Hintergrundfarbe von Elementen zu setzen. Diese Technik ermöglicht bedingte Stile, die nur gelten, wenn bestimmte Klassen zusammen erscheinen.",
+ "task": "Vervollständige die CSS-Regel, die Elemente mit sowohl card als auch featured-Klassen anvisiert, indem du die Selektoren verkettest. Setze border-color auf gold und background-color auf lemonchiffon, um hervorgehobene Karten hervorzuheben.",
+ "previewHTML": "
Mehrfach-Klassen-Kombinationen
\n
Normale Karte
\n
Hervorgehobene Karte
\n
Nur hervorgehoben (keine Karte)
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } .card { border: 2px solid gray; padding: 15px; margin-bottom: 10px; border-radius: 5px; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Die .card-Klasse hat bereits grundlegendes Styling */\n/* Visiere jetzt Elemente mit BEIDEN Klassen an: 'card' UND 'featured' */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": ".card.featured { border-color: gold; background-color: lemonchiffon }",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^\\.card\\.featured\\s*{",
+ "message": "Verkette die Selektoren als .card.featured (kein Leerzeichen dazwischen)",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "border-color:",
+ "message": "Füge die border-color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "border-color",
+ "expected": "gold"
+ },
+ "message": "Setze die Rahmenfarbe auf gold"
+ },
+ {
+ "type": "regex",
+ "value": "\\.card\\.featured\\s*{[^}]*;",
+ "message": "Vergiss nicht, deine CSS-Regel mit einem Semikolon ; zu beenden"
+ },
+ {
+ "type": "contains",
+ "value": "background-color:",
+ "message": "Füge die background-color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "lemonchiffon"
+ },
+ "message": "Setze die Hintergrundfarbe auf lemonchiffon"
+ },
+ {
+ "type": "regex",
+ "value": "\\.card\\.featured\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "class-with-type",
+ "title": "Typ- und Klassen-Selektoren kombinieren",
+ "description": "Du kannst Typ-Selektoren mit Klassen-Selektoren kombinieren, um bestimmte HTML-Elemente anzuvisieren, die eine bestimmte Klasse haben. Dies erstellt einen spezifischeren Selektor, der nur passt, wenn beide Bedingungen wahr sind: das Element ist vom angegebenen Typ UND es hat die angegebene Klasse. Zum Beispiel würde p.note Absatz-Elemente mit der Klasse note auswählen, aber keine divs oder spans mit derselben Klasse. Du kannst diese kombinierten Selektionen mit Eigenschaften wie background-color stylen, um einen farbigen Hintergrund für deine Elemente zu setzen. Dieser Ansatz ermöglicht es dir, verschiedene Stile auf dieselbe Klasse anzuwenden, wenn sie auf verschiedenen Elementtypen erscheint.",
+ "task": "Erstelle eine CSS-Regel, die speziell <span>-Elemente mit der Klasse highlight anvisiert. Gib diesen Elementen einen orangen Hintergrund, während andere Elemente mit der highlight-Klasse unverändert bleiben.",
+ "previewHTML": "
Typ- und Klassen-Kombinationen
\n
Dieser Absatz hat einen hervorgehobenen Span, der einen orangen Hintergrund haben sollte.
\n
Dieser Absatz hat die highlight-Klasse, sollte aber KEINEN orangen Hintergrund haben.
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } .highlight { font-weight: bold; }",
+ "sandboxCSS": "h2, p, span { padding: 5px; }",
+ "codePrefix": "/* Die .highlight-Klasse setzt bereits font-weight auf bold */\n/* Visiere jetzt NUR span-Elemente mit der highlight-Klasse an */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^span\\.highlight\\s*{",
+ "message": "Verwende den span.highlight-Selektor (kein Leerzeichen zwischen Element und Klasse)",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "background-color:",
+ "message": "Füge die background-color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "orange"
+ },
+ "message": "Setze die Hintergrundfarbe auf orange"
+ },
+ {
+ "type": "regex",
+ "value": "span\\.highlight\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "id-selectors",
+ "title": "ID-Selektoren: Einzigartige Elemente anvisieren",
+ "description": "ID-Selektoren visieren Elemente mit einem bestimmten id-Attribut an. Sie beginnen mit einem Raute-/Hash-Zeichen (#) gefolgt vom ID-Namen. Im Gegensatz zu Klassen müssen IDs innerhalb eines Dokuments einzigartig sein – jeder ID-Wert sollte nur einmal pro Seite verwendet werden. ID-Selektoren haben eine höhere Spezifität als Klassen- oder Element-Selektoren, was bedeutet, dass sie diese Selektoren bei Konflikten überschreiben. Beim Stylen mit ID-Selektoren kannst du Eigenschaften wie color verwenden, um die Textfarbe zu definieren, und text-decoration, um das Erscheinungsbild von Text zu kontrollieren, wie das Hinzufügen von Unterstreichungen zu Elementen. Wegen ihrer Einzigartigkeitsanforderung werden IDs am besten für einmalige Elemente wie Seitenköpfe, Hauptnavigation oder spezifische einzigartige Komponenten verwendet, die nur einmal auf einer Seite erscheinen.",
+ "task": "Erstelle eine CSS-Regel mit einem ID-Selektor, die das Element mit der ID main-title anvisiert. Setze seine Farbe auf purple und füge eine Unterstreichung mit text-decoration: underline hinzu.",
+ "previewHTML": "
Haupt-Seitentitel
\n
Normaler Absatzinhalt.
\n
Sekundäre Überschrift
\n
Einführungsabsatz (andere ID).
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; }",
+ "sandboxCSS": "h1, h2, p { padding: 8px; margin-bottom: 10px; border: 1px dashed #ccc; }",
+ "codePrefix": "/* Erstelle einen ID-Selektor für das Element mit id=\"main-title\" */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^#main-title\\s*{",
+ "message": "Beginne deine Regel mit #main-title, um einen ID-Selektor zu erstellen",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "purple"
+ },
+ "message": "Setze die Farbe auf purple"
+ },
+ {
+ "type": "contains",
+ "value": "text-decoration:",
+ "message": "Füge die text-decoration-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "text-decoration",
+ "expected": "underline"
+ },
+ "message": "Setze text-decoration auf underline"
+ },
+ {
+ "type": "regex",
+ "value": "#main-title\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "id-with-type",
+ "title": "Typ- und ID-Selektoren kombinieren",
+ "description": "Ähnlich wie du Typ- und Klassen-Selektoren kombinieren kannst, kannst du auch Typ-Selektoren mit ID-Selektoren kombinieren. Zum Beispiel visiert h1#title ein h1-Element mit der ID 'title' an. Bei diesem kombinierten Ansatz kannst du CSS-Eigenschaften wie font-style anwenden, um die Neigung des Textes zu kontrollieren und ihn kursiv oder normal zu machen. Obwohl diese Selektor-Kombination spezifischer ist als die Verwendung nur des ID-Selektors, ist sie oft unnötig, da IDs bereits einzigartig im Dokument sein sollten. Diese Technik kann jedoch nützlich sein, um die Lesbarkeit des Codes zu verbessern oder wenn du betonen möchtest, dass eine bestimmte ID nur auf einem bestimmten Elementtyp erscheinen sollte.",
+ "task": "Erstelle eine CSS-Regel, die einen Typ-Selektor mit einem ID-Selektor kombiniert, um speziell ein Absatz-Element mit der ID special anzuvisieren. Setze seinen Schriftstil auf kursiv.",
+ "previewHTML": "
Überschrift mit ID \"special\" (sollte NICHT betroffen sein)
\n
Absatz mit ID \"special\" (sollte kursiv werden)
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; }",
+ "sandboxCSS": "h2, p { padding: 8px; margin-bottom: 10px; border: 1px dashed #ccc; }",
+ "codePrefix": "/* Erstelle einen kombinierten Typ+ID-Selektor für einen Absatz mit id=\"special\" */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^p#special\\s*{",
+ "message": "Verwende p#special, um Absätze mit ID 'special' anzuvisieren",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "font-style:",
+ "message": "Füge die font-style-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "font-style",
+ "expected": "italic"
+ },
+ "message": "Setze font-style auf italic"
+ },
+ {
+ "type": "regex",
+ "value": "p#special\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "selector-lists",
+ "title": "Selektor-Listen: Gleiche Regeln auf mehrere Selektoren anwenden",
+ "description": "Wenn mehrere Elemente das gleiche Styling benötigen, kannst du sie mit einer Selektor-Liste (auch Gruppierungs-Selektoren genannt) zusammenfassen. Selektor-Listen werden erstellt, indem einzelne Selektoren durch Kommas getrennt werden. Dieser Ansatz reduziert Wiederholungen in deinem CSS und macht es wartbarer und effizienter. Zum Beispiel wendet h1, h2, h3 { color: blue; } die gleiche blaue Farbe auf alle drei Überschriftenebenen an. Beim Stylen mehrerer Selektoren gleichzeitig kannst du Eigenschaften wie background-color für den Hintergrund, border-left für einen linken Rahmen mit bestimmter Dicke, Stil und Farbe, und padding-left anwenden, um Abstand zwischen dem Inhalt und dem linken Rahmen zu schaffen. Leerzeichen um Kommas sind optional, und jeder Selektor in der Liste kann ein beliebiger gültiger Selektortyp sein – Elemente, Klassen, IDs oder sogar komplexere Selektoren.",
+ "task": "Erstelle eine Selektor-Liste, die die gleichen Stile auf drei verschiedene Elemente anwendet: Absätze mit der Klasse note, Listenelemente mit der Klasse important und das Element mit der ID summary. Gib ihnen einen lightyellow-Hintergrund, einen gold-linken Rahmen und etwas linkes padding.",
+ "previewHTML": "
Dies ist ein Notiz-Absatz.
\n
\n
Normales Listenelement
\n
Wichtiges Listenelement
\n
\n
Zusammenfassungs-Abschnitt
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; }",
+ "sandboxCSS": "p, li, div { padding: 8px; margin-bottom: 8px; border: 1px dashed gray; }",
+ "codePrefix": "/* Erstelle eine Selektor-Liste, um die gleichen Stile auf mehrere verschiedene Elemente anzuwenden */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "p.note,\nli.important,\n#summary {\n background-color: lightyellow;\n border-left: 3px solid gold;\n padding-left: 10px\n}",
+ "validations": [
+ {
+ "type": "contains",
+ "value": "p.note",
+ "message": "Füge p.note in deine Selektor-Liste ein",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "li.important",
+ "message": "Füge li.important in deine Selektor-Liste ein",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "#summary",
+ "message": "Füge #summary in deine Selektor-Liste ein",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "regex",
+ "value": "(p\\.note|li\\.important|#summary)\\s*,\\s*(p\\.note|li\\.important|#summary)\\s*,\\s*(p\\.note|li\\.important|#summary)",
+ "message": "Erstelle eine kommagetrennte Liste mit allen drei Selektoren",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "background-color:",
+ "message": "Füge die background-color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "lightyellow"
+ },
+ "message": "Setze die Hintergrundfarbe auf lightyellow"
+ },
+ {
+ "type": "contains",
+ "value": "border-left:",
+ "message": "Füge die border-left-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "border-left",
+ "expected": "3px solid gold"
+ },
+ "message": "Verwende border-left: 3px solid gold, um einen linken Rahmen zu erstellen"
+ },
+ {
+ "type": "contains",
+ "value": "padding-left:",
+ "message": "Füge die padding-left-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "padding-left",
+ "expected": "10px"
+ },
+ "message": "Verwende padding-left: 10px, um linkes Padding hinzuzufügen"
+ }
+ ]
+ },
+ {
+ "id": "universal-selector",
+ "title": "Der universelle Selektor: Alles anvisieren",
+ "description": "Der universelle Selektor wird durch ein Sternchen (*) gekennzeichnet und passt auf jedes Element jedes Typs. Er wählt alles im Dokument aus oder, wenn er mit anderen Selektoren kombiniert wird, alles innerhalb eines bestimmten Kontexts. Zum Beispiel entfernt * { margin: 0; } Ränder von allen Elementen, während article * alle Elemente innerhalb von article-Elementen auswählt. Bei der Verwendung des universellen Selektors in Kombination mit anderen Selektoren kannst du Eigenschaften wie margin anwenden, um die Abstände um Elemente zu kontrollieren. Der universelle Selektor ist mächtig, sollte aber wegen seiner breiten Auswirkung vorsichtig verwendet werden. Er wird häufig in CSS-Resets verwendet, um Standard-Browser-Styling zu überschreiben, oder um alle Kinder eines bestimmten Elements anzuvisieren.",
+ "task": "Verwende den universellen Selektor, um Ränder von allen Elementen innerhalb des Container-divs zu entfernen. Erstelle eine Regel mit div.container * als Selektor und setze margin: 0.",
+ "previewHTML": "
\n
Innerhalb des Containers
\n
Dieser Absatz ist innerhalb des Containers.
\n
\n
Listenelement innerhalb des Containers
\n
\n
\n
Dieser Absatz ist außerhalb des Containers und sollte nicht betroffen sein.
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } div.container { border: 2px solid navy; padding: 15px; background-color: lavender; } h2, p, ul, li { margin: 15px 0; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Verwende den universellen Selektor, um alle Elemente innerhalb des Containers anzuvisieren */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^div\\.container\\s+\\*\\s*{",
+ "message": "Verwende div.container *-Selektor (mit einem Leerzeichen zwischen container und *)",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "margin:",
+ "message": "Füge die margin-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "margin",
+ "expected": "0"
+ },
+ "message": "Setze margin auf 0"
+ },
+ {
+ "type": "regex",
+ "value": "div\\.container\\s+\\*\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "specificity-basics",
+ "title": "Selektor-Spezifität verstehen",
+ "description": "CSS-Spezifität bestimmt, welche Stile Vorrang haben, wenn mehrere widersprüchliche Regeln auf dasselbe Element abzielen. Spezifität folgt einem hierarchischen System: Inline-Stile haben die höchste Spezifität, gefolgt von ID-Selektoren, dann Klassen-/Attribut-/Pseudo-Klassen-Selektoren und schließlich Element-/Pseudo-Element-Selektoren. Dies kann als vierteilige Punktzahl (inline, ID, Klasse, Element) konzeptualisiert werden. Beim Erstellen mehrerer Regeln, die auf dieselben Elemente abzielen könnten, kannst du die color-Eigenschaft verwenden, um Textfarben zu setzen, und die Spezifität bestimmt, welche Farbe tatsächlich angewendet wird. Das Verstehen von Spezifität ist entscheidend für vorhersagbares Styling und das Debuggen von CSS-Konflikten. Wenn zwei Selektoren gleiche Spezifität haben, gewinnt derjenige, der zuletzt im Stylesheet kommt.",
+ "task": "Untersuche die vorhandenen CSS-Regeln und füge eine neue Regel mit höherer Spezifität hinzu, um die Textfarbe des Absatzes zu überschreiben. Erstelle eine Regel mit '.content p' als Selektor und setze color: green.",
+ "previewHTML": "
\n
Welche Farbe wird dieser Absatz haben? Schau dir die CSS-Regeln und ihre Spezifität an.
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; }",
+ "sandboxCSS": "p { border: 1px dashed gray; padding: 10px; }",
+ "codePrefix": "/* Diese CSS-Regeln visieren denselben Absatz an, haben aber unterschiedliche Spezifität */\n\n/* Regel 1: Element-Selektor (niedrigste Spezifität) */\np {\n color: red;\n}\n\n/* Regel 2: Nachfahren-Selektor (höhere Spezifität als nur 'p') */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^\\.content\\s+p\\s*{",
+ "message": "Verwende .content p als deinen Selektor (beachte das Leerzeichen dazwischen)",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color-Eigenschaft hinzu"
+ },
+ {
+ "type": "contains",
+ "value": "green",
+ "message": ""
+ }
+ ]
+ }
+ ]
+}
diff --git a/lessons/de/01-advanced-selectors.json b/lessons/de/01-advanced-selectors.json
new file mode 100644
index 0000000..f44bfcd
--- /dev/null
+++ b/lessons/de/01-advanced-selectors.json
@@ -0,0 +1,478 @@
+{
+ "$schema": "../../schemas/code-crispies-module-schema.json",
+ "id": "css-advanced-selectors",
+ "title": "CSS: Fortgeschrittene Selektoren",
+ "description": "Meistere fortgeschrittene CSS-Selektor-Techniken einschließlich Attribut-Selektoren, Kombinatoren und Pseudo-Klassen. Dieses Modul baut auf grundlegenden Selektoren auf und gibt dir präzise Kontrolle über die Elementauswahl, was ausgefeilte Styling-Muster und interaktive Effekte ermöglicht.",
+ "difficulty": "intermediate",
+ "lessons": [
+ {
+ "id": "attribute-selectors",
+ "title": "Attribut-Selektoren: Anvisieren nach HTML-Attributen",
+ "description": "Attribut-Selektoren ermöglichen es dir, Elemente basierend auf ihren HTML-Attributen und Attributwerten anzuvisieren. Sie sind unglaublich mächtig für das Styling von Formularen, Links und anderen Elementen mit spezifischen Attributen. Die grundlegende Syntax verwendet eckige Klammern: [attribute] wählt Elemente mit diesem Attribut, [attribute=\"value\"] wählt Elemente, bei denen das Attribut genau diesem Wert entspricht, und [attribute^=\"value\"] wählt Elemente, bei denen das Attribut mit diesem Wert beginnt. Du kannst diese ausgewählten Elemente mit Eigenschaften wie border stylen, um visuelle Grenzen hinzuzufügen, und background-color, um bestimmte Formularfelder oder Links hervorzuheben.",
+ "task": "Erstelle eine CSS-Regel mit einem Attribut-Selektor, die alle input-Elemente mit type=\"text\" anvisiert. Gib ihnen einen lightblue-Hintergrund und einen 2px solid blue-Rahmen.",
+ "previewHTML": "",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } form { max-width: 300px; } label { display: block; margin-bottom: 5px; } input, button { padding: 8px; margin-bottom: 10px; border-radius: 4px; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Visiere input-Elemente mit type=\"text\" mit einem Attribut-Selektor an */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "input[type=\"text\"] {\n background-color: lightblue;\n border: 2px solid blue\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^input\\[type=\"text\"\\]\\s*{",
+ "message": "Verwende input[type=\"text\"] { … } als deinen Attribut-Selektor",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "background-color:",
+ "message": "Füge die background-color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "lightblue"
+ },
+ "message": "Setze die Hintergrundfarbe auf lightblue"
+ },
+ {
+ "type": "regex",
+ "value": "background-color:\\s*[^;]*;",
+ "message": "Vergiss nicht, die background-color-Deklaration mit einem Semikolon ; zu beenden"
+ },
+ {
+ "type": "contains",
+ "value": "border:",
+ "message": "Füge die border-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "border",
+ "expected": "2px solid blue"
+ },
+ "message": "Setze den Rahmen auf 2px solid blue"
+ },
+ {
+ "type": "regex",
+ "value": "input\\[type=\"text\"\\]\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "attribute-partial-matching",
+ "title": "Teilweises Attribut-Matching",
+ "description": "Attribut-Selektoren unterstützen teilweise Matching-Muster, die es dir ermöglichen, Elemente basierend auf Teilen von Attributwerten anzuvisieren. Der [attribute^=\"value\"]-Selektor passt auf Elemente, bei denen das Attribut mit dem angegebenen Wert beginnt, [attribute$=\"value\"] passt, wenn es mit dem Wert endet, und [attribute*=\"value\"] passt, wenn der Wert irgendwo innerhalb des Attributs erscheint. Diese Muster sind besonders nützlich für das Styling externer Links, Dateitypen oder Elemente mit Klassennamen, die Namenskonventionen folgen. Beim Stylen dieser gematchten Elemente kannst du Eigenschaften wie color verwenden, um die Textfarbe zu ändern, und text-decoration, um visuelle Betonung wie Unterstreichungen hinzuzufügen.",
+ "task": "Erstelle eine CSS-Regel, die alle Anker-Elemente (a) mit href-Attributen, die mit \"https\" beginnen, anvisiert. Style sie mit green-Textfarbe und underline-Textdekoration.",
+ "previewHTML": "
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } ul { list-style-type: none; padding: 0; } li { margin-bottom: 8px; } a { text-decoration: none; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Visiere Anker-Elemente an, deren href mit \"https\" beginnt */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "a[href^=\"https\"] {\n color: green;\n text-decoration: underline;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^a\\[href\\^=\"https\"\\]\\s*{",
+ "message": "Verwende a[href^=\"https\"] { … } als deinen Attribut-Selektor, um HTTPS-Links anzuvisieren",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color-Eigenschaft hinzu, um die Textfarbe zu setzen"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "green"
+ },
+ "message": "Setze die Textfarbe auf green"
+ },
+ {
+ "type": "contains",
+ "value": "text-decoration:",
+ "message": "Füge die text-decoration-Eigenschaft hinzu, um das Link-Erscheinungsbild zu stylen"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "text-decoration",
+ "expected": "underline"
+ },
+ "message": "Setze text-decoration auf underline, um HTTPS-Links zu unterstreichen"
+ },
+ {
+ "type": "regex",
+ "value": "a\\[href\\^=\"https\"\\]\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "child-combinator",
+ "title": "Kind-Kombinator: Nur direkte Kinder",
+ "description": "Der Kind-Kombinator (>) wählt Elemente aus, die direkte Kinder eines anderen Elements sind, keine Enkel oder tiefere Nachfahren. Dies ist entscheidend, wenn du verschachtelte Strukturen hast, bei denen du nur die äußere Ebene stylen möchtest. Zum Beispiel könntest du in einem Navigationsmenü mit Dropdowns möchten, dass Hauptmenüpunkte anders gestylt werden als Untermenüpunkte. Der Kind-Kombinator (>) gibt dir chirurgische Präzision – ul > li visiert nur direkte Listenelemente an, während ul li ALLE Listenelemente einschließlich verschachtelter anvisieren würde. Dies verhindert Stil-Vererbungschaos in komplexen Layouts.",
+ "task": "Verwende den Kind-Kombinator, um nur die direkten li-Kinder von .main-nav anzuvisieren. Gib ihnen einen cornflowerblue-Hintergrund und white-Textfarbe. Beachte, wie die verschachtelten Untermenü-Elemente völlig ungestylt bleiben!",
+ "previewHTML": "
\n
🏠 Startseite
\n
📱 Produkte\n
\n
💻 Laptops
\n
📱 Handys
\n
⌚ Uhren
\n
\n
\n
ℹ️ Über uns\n
\n
👥 Team
\n
📍 Standort
\n
\n
\n
📧 Kontakt
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; padding: 20px; background: #f5f5f5; } .main-nav { background: white; border-radius: 8px; padding: 0; margin: 0; box-shadow: 0 2px 8px rgba(0,0,0,0.1); list-style: none; } .main-nav li { padding: 12px 16px; margin: 2px 0; cursor: pointer; transition: all 0.2s; } .main-nav ul { margin: 8px 0 0 20px; padding: 0; list-style: none; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Visiere nur die direkten li-Kinder von .main-nav an (nicht verschachtelte Untermenü-Elemente) */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": ".main-nav > li {\n background-color: cornflowerblue;\n color: white;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^\\.main-nav\\s*>\\s*li\\s*{",
+ "message": "Verwende .main-nav > li { … } mit dem Kind-Kombinator, um nur direkte Kinder anzuvisieren",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "background-color:",
+ "message": "Füge die background-color-Eigenschaft hinzu, um Hauptmenüpunkte hervorzuheben"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "cornflowerblue"
+ },
+ "message": "Setze background-color auf cornflowerblue für das Hauptmenü-Styling"
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color-Eigenschaft hinzu, um die Textfarbe zu setzen"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "white"
+ },
+ "message": "Setze die Textfarbe auf white für Kontrast gegen den blauen Hintergrund"
+ },
+ {
+ "type": "regex",
+ "value": "\\.main-nav\\s*>\\s*li\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "descendant-combinator",
+ "title": "Nachfahren-Kombinator: Alle verschachtelten Elemente",
+ "description": "Der Nachfahren-Kombinator verwendet ein Leerzeichen zwischen Selektoren, um Elemente anzuvisieren, die irgendwo in anderen Elementen verschachtelt sind, unabhängig davon, wie tief verschachtelt sie sind. Zum Beispiel wählt nav a alle Anker-Elemente innerhalb von Navigations-Elementen aus, ob sie direkte Kinder oder mehrere Ebenen tief verschachtelt sind. Dies ist breiter als der Kind-Kombinator und nützlich für das Anwenden einheitlichen Stylings auf alle Elemente eines bestimmten Typs innerhalb eines Containers. Beim Stylen von Nachfahren kannst du Eigenschaften wie text-decoration verwenden, um das Link-Erscheinungsbild zu kontrollieren, und color, um einheitliche Textfarben in einem Abschnitt zu setzen. Der Nachfahren-Kombinator ist einer der am häufigsten verwendeten Kombinatoren in CSS.",
+ "task": "Verwende den Nachfahren-Kombinator, um alle Anker-Elemente (a) innerhalb des nav-Elements anzuvisieren. Entferne ihre Unterstreichungen mit text-decoration: none und mache sie blue.",
+ "previewHTML": "\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } nav { border: 2px solid navy; padding: 15px; background-color: aliceblue; margin-bottom: 15px; } ul { list-style-type: none; padding-left: 20px; } li { margin-bottom: 5px; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Visiere alle Anker-Elemente innerhalb von nav mit dem Nachfahren-Kombinator an */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "nav a {\n text-decoration: none;\n color: blue;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^nav\\s+a\\s*{",
+ "message": "Verwende nav a mit einem Leerzeichen zwischen nav und a",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "text-decoration:",
+ "message": "Füge die text-decoration-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "text-decoration",
+ "expected": "none"
+ },
+ "message": "Setze text-decoration auf none"
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "blue"
+ },
+ "message": "Setze color auf blue"
+ },
+ {
+ "type": "regex",
+ "value": "nav\\s+a\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "adjacent-sibling-combinator",
+ "title": "Benachbarter-Geschwister-Kombinator: Das nächste Element",
+ "description": "Der benachbarte-Geschwister-Kombinator (+) wählt ein Element aus, das einem anderen Element auf derselben Ebene in der HTML-Struktur unmittelbar folgt. Beide Elemente müssen denselben Elternteil haben, und es dürfen keine anderen Elemente zwischen ihnen sein. Zum Beispiel wählt h1 + p Absatz-Elemente aus, die direkt nach h1-Überschriften kommen. Dieser Kombinator ist besonders nützlich für das Styling von Elementen, die besondere Beziehungen haben, wie der erste Absatz nach einer Überschrift oder Labels, die Formulareingaben folgen. Beim Stylen benachbarter Geschwister kannst du Eigenschaften wie margin-top verwenden, um Abstände anzupassen, und font-style, um Betonung wie Kursivschrift hinzuzufügen, um visuelle Hierarchie zu schaffen.",
+ "task": "Verwende den benachbarten-Geschwister-Kombinator, um Absätze anzuvisieren, die unmittelbar auf h2-Überschriften folgen. Entferne ihren oberen Rand mit margin-top: 0 und mache sie kursiv.",
+ "previewHTML": "
Erste Überschrift
\n
Dieser Absatz folgt direkt auf h2 (sollte betroffen sein).
\n
Dieser Absatz kommt nach einem anderen Absatz (sollte NICHT betroffen sein).
\n
Zweite Überschrift
\n
Dieser Absatz folgt auch direkt auf h2 (sollte betroffen sein).
\n
Dieses div kommt nach h2, ist aber kein Absatz.
\n
Dieser Absatz kommt nach einem div (sollte NICHT betroffen sein).
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } h2, p, div { margin: 15px 0; padding: 8px; border: 1px dashed #ccc; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Visiere Absätze an, die unmittelbar auf h2-Überschriften folgen */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "h2 + p {\n margin-top: 0;\n font-style: italic;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^h2\\s*\\+\\s*p\\s*{",
+ "message": "Verwende h2 + p mit dem benachbarten-Geschwister-Kombinator (+)",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "margin-top:",
+ "message": "Füge die margin-top-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "margin-top",
+ "expected": "0"
+ },
+ "message": "Setze margin-top auf 0"
+ },
+ {
+ "type": "contains",
+ "value": "font-style:",
+ "message": "Füge die font-style-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "font-style",
+ "expected": "italic"
+ },
+ "message": "Setze font-style auf italic"
+ },
+ {
+ "type": "regex",
+ "value": "h2\\s*\\+\\s*p\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "general-sibling-combinator",
+ "title": "Allgemeiner-Geschwister-Kombinator: Alle folgenden Geschwister",
+ "description": "Der allgemeine-Geschwister-Kombinator (~) wählt alle Elemente aus, die einem anderen Element auf derselben Ebene folgen, nicht nur das unmittelbar benachbarte. Im Gegensatz zum benachbarten-Geschwister-Kombinator können andere Elemente zwischen den Zielelementen sein, solange sie alle denselben Elternteil haben und die ausgewählten Elemente nach dem Referenzelement kommen. Zum Beispiel wählt h2 ~ p alle Absatz-Elemente aus, die nach einer h2-Überschrift auf derselben Ebene erscheinen. Beim Stylen allgemeiner Geschwister kannst du Eigenschaften wie color verwenden, um die Textfarbe zu ändern, und padding-left, um visuelle Einrückung zu schaffen, was hilft, die Beziehung zwischen verwandten Inhaltsabschnitten zu zeigen.",
+ "task": "Verwende den allgemeinen-Geschwister-Kombinator, um alle Absätze anzuvisieren, die nach der h3-Überschrift kommen (auf derselben Ebene). Gib ihnen eine gray-Farbe und 20px linkes Padding.",
+ "previewHTML": "
\n
Dieser Absatz kommt vor h3 (sollte NICHT betroffen sein).
\n
Abschnittstitel
\n
Erster Absatz nach h3 (sollte betroffen sein).
\n
Etwas anderer Inhalt dazwischen
\n
Zweiter Absatz nach h3 (sollte auch betroffen sein).
\n Mehr Inhalt\n
Dritter Absatz nach h3 (sollte auch betroffen sein).
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } h3, p, div, span { margin: 10px 0; padding: 8px; border: 1px dashed #ccc; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Visiere alle Absätze an, die h3 folgen, mit dem allgemeinen-Geschwister-Kombinator */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "h3 ~ p {\n color: gray;\n padding-left: 20px;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^h3\\s*~\\s*p\\s*{",
+ "message": "Verwende h3 ~ p mit dem allgemeinen-Geschwister-Kombinator (~)",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "gray"
+ },
+ "message": "Setze color auf gray"
+ },
+ {
+ "type": "contains",
+ "value": "padding-left:",
+ "message": "Füge die padding-left-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "padding-left",
+ "expected": "20px"
+ },
+ "message": "Setze padding-left auf 20px"
+ },
+ {
+ "type": "regex",
+ "value": "h3\\s*~\\s*p\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "hover-pseudo-class",
+ "title": "Die :hover Pseudo-Klasse",
+ "description": "Die :hover Pseudo-Klasse wendet Stile an, wenn ein Benutzer mit der Maus über ein Element fährt. Dies schafft interaktives Feedback, das die Benutzererfahrung verbessert, indem es visuelle Hinweise über klickbare oder interaktive Elemente gibt. Hover-Effekte werden häufig bei Links, Buttons und anderen interaktiven Elementen verwendet, um ihre interaktive Natur anzuzeigen. Beim Erstellen von Hover-Effekten kannst du Eigenschaften wie background-color verwenden, um den Hintergrund beim Hover zu ändern, und color, um die Textfarbe zu ändern, was klares visuelles Feedback schafft. Die :hover Pseudo-Klasse gilt nur, während der Mauszeiger über dem Element positioniert ist, und kehrt zum normalen Zustand zurück, wenn der Zeiger sich entfernt.",
+ "task": "Erstelle einen Hover-Effekt für das Button-Element. Beim Hover ändere den Hintergrund auf darkblue und die Textfarbe auf white.",
+ "previewHTML": "
Interaktiver Button
\n
Fahre mit der Maus über den Button unten, um den Effekt zu sehen:
\n\n
Der Button sollte seine Farben ändern, wenn du mit der Maus darüber fährst.
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } button { padding: 12px 24px; font-size: 16px; border: 2px solid darkblue; background-color: lightblue; color: darkblue; border-radius: 5px; cursor: pointer; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Erstelle einen Hover-Effekt für den Button */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "button:hover {\n background-color: darkblue;\n color: white;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^button:hover\\s*{",
+ "message": "Verwende button:hover, um Buttons beim Hover anzuvisieren",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "background-color:",
+ "message": "Füge die background-color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "background-color",
+ "expected": "darkblue"
+ },
+ "message": "Setze background-color auf darkblue"
+ },
+ {
+ "type": "contains",
+ "value": "color:",
+ "message": "Füge die color-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "color",
+ "expected": "white"
+ },
+ "message": "Setze color auf white"
+ },
+ {
+ "type": "regex",
+ "value": "button:hover\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "first-child-pseudo-class",
+ "title": "Die :first-child Pseudo-Klasse",
+ "description": "Die :first-child Pseudo-Klasse wählt Elemente aus, die das erste Kind ihres Elternelements sind. Dies ist nützlich für das Anwenden spezieller Stile auf das erste Element in Listen, den ersten Absatz in Artikeln oder das erste Element in einem beliebigen Container. Zum Beispiel wählt li:first-child das erste Listenelement in jeder Liste aus, während p:first-child Absätze auswählt, die das erste Kind-Element ihres Containers sind. Beim Stylen erster Kinder kannst du Eigenschaften wie font-weight verwenden, um das erste Element fett zu machen, und margin-top, um Abstände anzupassen, was hilft, visuelle Hierarchie zu schaffen und das Layout deines Inhalts zu verbessern.",
+ "task": "Verwende die :first-child Pseudo-Klasse, um das erste Listenelement in jeder Liste anzuvisieren. Mache es bold und entferne seinen oberen Rand.",
+ "previewHTML": "
Mehrere Listen
\n
Früchte
\n
\n
Apfel (erstes Kind)
\n
Banane
\n
Orange
\n
\n
Farben
\n
\n
Rot (erstes Kind)
\n
Blau
\n
Grün
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; line-height: 1.5; padding: 20px; } li { margin: 8px 0; padding: 5px; border: 1px solid #ddd; border-radius: 3px; }",
+ "sandboxCSS": "",
+ "codePrefix": "/* Visiere das erste Listenelement in jeder Liste an */\n",
+ "initialCode": "",
+ "codeSuffix": "",
+ "previewContainer": "preview-area",
+ "solution": "li:first-child {\n font-weight: bold;\n margin-top: 0;\n}",
+ "validations": [
+ {
+ "type": "regex",
+ "value": "^li:first-child\\s*{",
+ "message": "Verwende li:first-child, um erste Listenelemente anzuvisieren",
+ "options": {
+ "caseSensitive": true
+ }
+ },
+ {
+ "type": "contains",
+ "value": "font-weight:",
+ "message": "Füge die font-weight-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "font-weight",
+ "expected": "bold"
+ },
+ "message": "Setze font-weight auf bold"
+ },
+ {
+ "type": "contains",
+ "value": "margin-top:",
+ "message": "Füge die margin-top-Eigenschaft hinzu"
+ },
+ {
+ "type": "property_value",
+ "value": {
+ "property": "margin-top",
+ "expected": "0"
+ },
+ "message": "Setze margin-top auf 0"
+ },
+ {
+ "type": "regex",
+ "value": "li:first-child\\s*{[^}]*}",
+ "message": "Vergiss nicht, deine CSS-Regel mit einer schließenden Klammer } zu beenden",
+ "options": {
+ "caseSensitive": true
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/lessons/de/10-tailwind-basics.json b/lessons/de/10-tailwind-basics.json
new file mode 100644
index 0000000..237b6d0
--- /dev/null
+++ b/lessons/de/10-tailwind-basics.json
@@ -0,0 +1,160 @@
+{
+ "$schema": "../../schemas/code-crispies-module-schema.json",
+ "id": "tailwind-basics",
+ "title": "Tailwind: Grundlagen",
+ "description": "Lerne, wie Tailwind CSS das Styling revolutioniert, indem es traditionelle CSS-Selektoren durch Utility-First-Klassen ersetzt. Verstehe die Philosophie hinter Utility-Klassen und wie sie häufige CSS-Probleme wie Spezifitätskonflikte und Wartungskomplexität lösen.",
+ "mode": "tailwind",
+ "difficulty": "beginner",
+ "lessons": [
+ {
+ "id": "bg-colors",
+ "title": "Hintergrundfarben",
+ "description": "Lerne, Hintergrundfarben mit Tailwind-Utilities anzuwenden.",
+ "task": "Füge dem div einen blauen Hintergrund mit Tailwind-Klassen hinzu.",
+ "previewHTML": "
Hallo Tailwind!
",
+ "previewBaseCSS": "body { padding: 20px; font-family: sans-serif; }",
+ "sandboxCSS": "",
+ "initialCode": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "contains_class",
+ "value": "bg-blue-500",
+ "message": "Füge die 'bg-blue-500'-Klasse für einen blauen Hintergrund hinzu."
+ }
+ ]
+ },
+ {
+ "id": "utility-first-philosophy",
+ "title": "Den Utility-First-Ansatz verstehen",
+ "description": "Tailwind CSS folgt einem Utility-First-Ansatz, bei dem du anstelle von benutzerdefinierten CSS-Klassen Designs mit kleinen, einzweckigen Utility-Klassen zusammenstellst. Im Gegensatz zu traditionellem CSS, wo du möglicherweise .card { background: white; padding: 1rem; border-radius: 0.5rem; } schreibst, bietet Tailwind vorgefertigte Utilities wie bg-white, p-4 und rounded.
Das bg-white-Utility setzt background-color: white, p-4 wendet padding: 1rem auf allen Seiten an, und rounded fügt border-radius: 0.25rem hinzu. Dieser Ansatz eliminiert die Notwendigkeit, zwischen HTML- und CSS-Dateien zu wechseln.",
+ "task": "Erstelle einen weißen kartenähnlichen Container mit einem kleinen Schlagschatten, 1rem Padding und abgerundeten Ecken.",
+ "previewHTML": "
\n
\n
Kartentitel
\n
Dies ist eine Karten-Komponente, die vollständig mit Utility-Klassen erstellt wurde!
\n
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; margin: 0; }",
+ "sandboxCSS": "/* Traditioneller CSS-Ansatz:\n.card {\n background-color: white;\n padding: 1rem;\n border-radius: 0.25rem;\n}\n*/",
+ "initialCode": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "contains_class",
+ "value": "bg-white",
+ "message": "Füge bg-white hinzu, um die Hintergrundfarbe auf weiß zu setzen."
+ },
+ {
+ "type": "contains_class",
+ "value": "p-4",
+ "message": "Füge p-4 hinzu, um 1rem Padding auf allen Seiten anzuwenden."
+ },
+ {
+ "type": "contains_class",
+ "value": "rounded",
+ "message": "Füge rounded hinzu, um einen border-radius von 0.25rem anzuwenden."
+ },
+ {
+ "type": "contains_class",
+ "value": "shadow-sm",
+ "message": "Füge shadow-sm hinzu, um einen kleinen Schlagschatten anzuwenden."
+ }
+ ]
+ },
+ {
+ "id": "text-utilities",
+ "title": "Textfarbe und Größen-Utilities",
+ "description": "Tailwind bietet umfassende Text-Utilities für Typografie-Styling. Textfarben verwenden das Muster text-{farbe}-{abstufung}, wobei Farben rot, blau, grün usw. umfassen und Abstufungen von 50 (hellste) bis 950 (dunkelste) reichen. Zum Beispiel wendet text-blue-600 eine mittlere Blaufarbe an.
Textgrößen folgen dem Muster text-{größe} mit Optionen wie text-sm (0.875rem), text-base (1rem), text-lg (1.125rem), text-xl (1.25rem) und größeren Größen bis zu text-9xl. Schriftgewichte verwenden font-{gewicht} wie font-normal, font-medium, font-semibold und font-bold.",
+ "task": "Style die Überschrift mit text-blue-600 für die Farbe, text-2xl für die Größe und font-bold für das Gewicht.",
+ "previewHTML": "
\n
Willkommen bei Tailwind CSS
\n
Diese Überschrift demonstriert Text-Utilities in Aktion.
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; margin: 0; }",
+ "sandboxCSS": "/* Traditionelles CSS wäre:\nh1 {\n color: #2563eb;\n font-size: 1.5rem;\n font-weight: 700;\n}\n*/",
+ "initialCode": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "contains_class",
+ "value": "text-blue-600",
+ "message": "Füge text-blue-600 hinzu, um den Text blau zu machen"
+ },
+ {
+ "type": "contains_class",
+ "value": "text-2xl",
+ "message": "Füge text-2xl hinzu, um die Schriftgröße auf 1.5rem zu erhöhen"
+ },
+ {
+ "type": "contains_class",
+ "value": "font-bold",
+ "message": "Füge font-bold hinzu, um den Text fett zu machen (font-weight: 700)"
+ }
+ ]
+ },
+ {
+ "id": "spacing-utilities",
+ "title": "Abstände mit Padding und Margin",
+ "description": "Tailwinds Abstands-Utilities folgen einem konsistenten Muster mit einer Abstandsskala, bei der jede Einheit 0.25rem (4px) darstellt. Padding-Utilities verwenden p-{größe} für alle Seiten, px-{größe} für horizontal (links/rechts), py-{größe} für vertikal (oben/unten), oder einzelne Seiten wie pt-{größe}, pr-{größe}, pb-{größe}, pl-{größe}.
Häufige Größen sind p-2 (0.5rem), p-4 (1rem), p-6 (1.5rem) und p-8 (2rem). Margin folgt demselben Muster, verwendet aber m- statt p-. Zum Beispiel zentriert mx-auto ein Element horizontal durch automatische linke und rechte Margins.",
+ "task": "Style den Button mit px-6 für horizontales Padding, py-3 für vertikales Padding und mx-auto, um ihn zu zentrieren.",
+ "previewHTML": "
\n \n
",
+ "previewBaseCSS": "body { font-family: sans-serif; margin: 0; }",
+ "sandboxCSS": "/* Traditionelles CSS-Äquivalent:\nbutton {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n margin-left: auto;\n margin-right: auto;\n}\n*/",
+ "initialCode": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "contains_class",
+ "value": "px-6",
+ "message": "Füge px-6 für horizontales Padding hinzu (1.5rem links und rechts)"
+ },
+ {
+ "type": "contains_class",
+ "value": "py-3",
+ "message": "Füge py-3 für vertikales Padding hinzu (0.75rem oben und unten)"
+ },
+ {
+ "type": "contains_class",
+ "value": "mx-auto",
+ "message": "Füge mx-auto hinzu, um den Button horizontal zu zentrieren"
+ }
+ ]
+ },
+ {
+ "id": "responsive-design",
+ "title": "Responsives Design mit Breakpoint-Präfixen",
+ "description": "Tailwind verwendet einen Mobile-First-Ansatz für responsives Design mit Breakpoint-Präfixen. Die Basis-Utilities gelten für alle Bildschirmgrößen, dann fügst du Präfixe für größere Bildschirme hinzu: sm: (640px+), md: (768px+), lg: (1024px+), xl: (1280px+) und 2xl: (1536px+).
Zum Beispiel macht text-base md:text-lg lg:text-xl Text auf Mobil normal groß, größer auf Tablets (md) und noch größer auf Desktop (lg). Jeder Breakpoint überschreibt den vorherigen, also bedeutet p-4 md:p-6 lg:p-8 1rem Padding auf Mobil, 1.5rem auf Tablets und 2rem auf Desktop.
Breiten-Utilities wie w-full (100% Breite), w-1/2 (50% Breite) oder feste Größen wie w-64 (16rem) können auch responsiv gemacht werden.",
+ "task": "Mache die Box responsiv: w-full auf Mobil, md:w-1/2 auf Tablets und lg:w-1/3 auf Desktop. Füge auch responsive Textgrößen hinzu mit text-lg, md:text-xl und lg:text-2xl.",
+ "previewHTML": "
\n
\n Responsive Box \n Ändere die Browsergröße, um den Effekt zu sehen!\n
\n
",
+ "previewBaseCSS": "body { font-family: sans-serif; margin: 0; }",
+ "sandboxCSS": "/* Traditionelles CSS würde Media Queries erfordern:\n.responsive-box {\n width: 100%;\n font-size: 1.125rem;\n}\n@media (min-width: 768px) {\n .responsive-box {\n width: 50%;\n font-size: 1.25rem;\n }\n}\n@media (min-width: 1024px) {\n .responsive-box {\n width: 33.333333%;\n font-size: 1.5rem;\n }\n}\n*/",
+ "initialCode": "",
+ "previewContainer": "preview-area",
+ "validations": [
+ {
+ "type": "contains_class",
+ "value": "w-full",
+ "message": "Füge w-full für 100% Breite auf Mobil hinzu"
+ },
+ {
+ "type": "contains_class",
+ "value": "md:w-1/2",
+ "message": "Füge md:w-1/2 für 50% Breite auf Tablet und größer hinzu"
+ },
+ {
+ "type": "contains_class",
+ "value": "lg:w-1/3",
+ "message": "Füge lg:w-1/3 für 33.33% Breite auf Desktop und größer hinzu"
+ },
+ {
+ "type": "contains_class",
+ "value": "text-lg",
+ "message": "Füge text-lg für die Basis-Textgröße hinzu"
+ },
+ {
+ "type": "contains_class",
+ "value": "md:text-xl",
+ "message": "Füge md:text-xl für größeren Text auf Tablets hinzu"
+ },
+ {
+ "type": "contains_class",
+ "value": "lg:text-2xl",
+ "message": "Füge lg:text-2xl für noch größeren Text auf Desktop hinzu"
+ }
+ ]
+ }
+ ]
+}
diff --git a/lessons/de/20-html-elements.json b/lessons/de/20-html-elements.json
new file mode 100644
index 0000000..285c909
--- /dev/null
+++ b/lessons/de/20-html-elements.json
@@ -0,0 +1,97 @@
+{
+ "$schema": "../../schemas/code-crispies-module-schema.json",
+ "id": "html-elements",
+ "title": "HTML-Elemente: Block vs Inline",
+ "description": "Verstehe den grundlegenden Unterschied zwischen Container- (Block-) und Inline-Elementen",
+ "mode": "html",
+ "difficulty": "beginner",
+ "lessons": [
+ {
+ "id": "block-vs-inline-intro",
+ "title": "Block- vs Inline-Elemente",
+ "description": "HTML-Elemente fallen in zwei Hauptkategorien:
Block-Elemente (Container) beginnen in einer neuen Zeile und nehmen die volle Breite ein. Beispiele: <div>, <p>, <h1>, <section>
Inline-Elemente fließen innerhalb des Textes und nehmen nur die benötigte Breite ein. Beispiele: <span>, <a>, <strong>, <em>",
+ "task": "Umschließe das Wort wichtig mit <strong>-Tags, um es fett zu machen. Beachte, wie der Absatz (Block) die volle Breite einnimmt, während strong (Inline) mit dem Text fließt.",
+ "previewHTML": "",
+ "previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 20px; } p { background: #e3f2fd; padding: 10px; } strong { background: #ffecb3; }",
+ "sandboxCSS": "",
+ "initialCode": "
Absatz-Element hinzu"
+ },
+ {
+ "type": "parent_child",
+ "value": { "parent": "p", "child": "strong" },
+ "message": "Umschließe das Wort 'wichtig' mit -Tags"
+ }
+ ]
+ },
+ {
+ "id": "semantic-containers",
+ "title": "Semantische Container-Elemente",
+ "description": "Modernes HTML verwendet semantische Container, die ihren Inhalt beschreiben:
<header> - Kopfbereich der Seite oder eines Abschnitts <nav> - Navigationslinks <main> - Hauptinhalt <section> - Thematische Gruppierung <article> - Eigenständiger Inhalt <footer> - Fußbereich der Seite oder eines Abschnitts",
+ "task": "Erstelle eine einfache Seitenstruktur: 1. Füge ein <header> mit einem <h1> hinzu, das den Text 'Meine Webseite' enthält 2. Füge ein <main>-Element mit einem Absatz hinzu, der 'Willkommen auf meiner Seite!' sagt 3. Füge ein <footer> mit einem Absatz hinzu, der 'Copyright 2025' sagt",
+ "previewHTML": "",
+ "previewBaseCSS": "body { font-family: system-ui; margin: 0; } header { background: #1976d2; color: white; padding: 15px; } main { padding: 20px; min-height: 100px; } footer { background: #424242; color: white; padding: 10px; text-align: center; }",
+ "sandboxCSS": "",
+ "initialCode": "",
+ "solution": "\n