Skip to content

Commit 573c672

Browse files
nextlevelshitclaude
andcommitted
feat: add CSS lessons matching lecture content (box model, flexbox, responsive, transitions, variables)
- Add 5 CSS modules to lessons.js config (EN) - Create German translations for all 5 CSS modules - Add CSS modules to lessons.de.js config - Fix test to use toBeGreaterThanOrEqual for module count 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 79b6ece commit 573c672

File tree

8 files changed

+805
-2
lines changed

8 files changed

+805
-2
lines changed

lessons/de/01-box-model.json

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
{
2+
"$schema": "../../schemas/code-crispies-module-schema.json",
3+
"id": "box-model",
4+
"title": "Padding, Borders und Margins",
5+
"description": "Beherrsche die Grundprinzipien der Raumverwaltung im Webdesign durch das CSS Box-Modell.",
6+
"difficulty": "beginner",
7+
"lessons": [
8+
{
9+
"id": "box-model-1",
10+
"title": "Box-Modell Komponenten",
11+
"description": "Das CSS Box-Modell besteht aus vier konzentrischen Schichten: Inhalt (innerste), Padding, Border und Margin (äußerste). Zu verstehen, wie diese Komponenten zusammenwirken, ist essentiell für präzise Layout-Kontrolle.",
12+
"task": "Füge dem Box-Element ein Padding von '1.25rem' hinzu, um Abstand zwischen Inhalt und Rahmen zu schaffen.",
13+
"previewHTML": "<div class=\"box\">Box-Modell Komponenten</div>",
14+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .box { background-color: #f0f0f0; border: 0.125rem dashed #aaa; }",
15+
"sandboxCSS": "",
16+
"codePrefix": "/* Füge Padding zum Box-Element hinzu */\n.box {\n /* Füge deinen Code unten ein */\n ",
17+
"initialCode": "",
18+
"codeSuffix": "\n}",
19+
"previewContainer": "preview-area",
20+
"validations": [
21+
{
22+
"type": "contains",
23+
"value": "padding",
24+
"message": "Verwende die 'padding' Eigenschaft",
25+
"options": { "caseSensitive": false }
26+
},
27+
{
28+
"type": "property_value",
29+
"value": { "property": "padding", "expected": "1.25rem" },
30+
"message": "Setze padding auf genau '1.25rem'"
31+
}
32+
]
33+
},
34+
{
35+
"id": "box-model-2",
36+
"title": "Rahmen hinzufügen",
37+
"description": "Rahmen umranden ein Element und schaffen visuelle Trennung. CSS erlaubt die Kontrolle von Dicke, Stil (solid, dashed, dotted, etc.) und Farbe.",
38+
"task": "Füge einen durchgezogenen Rahmen mit Dicke '0.125rem' und Farbe '#333' hinzu. Die border-Eigenschaft akzeptiert drei Werte: Breite, Stil und Farbe.",
39+
"previewHTML": "<div class=\"box\">Diese Box braucht einen Rahmen</div>",
40+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .box { background-color: #f0f0f0; padding: 1.25rem; }",
41+
"sandboxCSS": "",
42+
"codePrefix": "/* Füge einen Rahmen zur Box hinzu */\n.box {\n /* Füge deinen Code unten ein */\n ",
43+
"initialCode": "",
44+
"codeSuffix": "\n}",
45+
"previewContainer": "preview-area",
46+
"validations": [
47+
{
48+
"type": "contains",
49+
"value": "border",
50+
"message": "Verwende die 'border' Eigenschaft",
51+
"options": { "caseSensitive": false }
52+
},
53+
{
54+
"type": "regex",
55+
"value": "border:\\s*0.125rem\\s+solid\\s+#333",
56+
"message": "Setze border auf '0.125rem solid #333'",
57+
"options": { "caseSensitive": false }
58+
},
59+
{
60+
"type": "contains",
61+
"value": "solid",
62+
"message": "Verwende 'solid' als Rahmenstil",
63+
"options": { "caseSensitive": false }
64+
}
65+
]
66+
},
67+
{
68+
"id": "box-model-3",
69+
"title": "Außenabstände hinzufügen",
70+
"description": "Margins schaffen Abstand zwischen Elementen. Anders als Padding (das den inneren Abstand beeinflusst) existiert Margin außerhalb des Rahmens.",
71+
"task": "Füge dem Box-Element einen Margin von '1rem' hinzu, um Abstand zu benachbarten Elementen zu schaffen.",
72+
"previewHTML": "<div class=\"container\"><div class=\"margin-box\">Diese Box braucht Margins</div><div class=\"neighbor\">Benachbartes Element</div></div>",
73+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .container { background-color: #f8f8f8; padding: 0.5rem; } .margin-box { background-color: #d1c4e9; padding: 1rem; border: 0.125rem solid #7e57c2; } .neighbor { background-color: #bbdefb; padding: 1rem; border: 0.125rem solid #42a5f5; }",
74+
"sandboxCSS": "",
75+
"codePrefix": "/* Füge Margin zur Box hinzu */\n.margin-box {\n /* Füge deinen Code unten ein */\n ",
76+
"initialCode": "",
77+
"codeSuffix": "\n}",
78+
"previewContainer": "preview-area",
79+
"validations": [
80+
{
81+
"type": "contains",
82+
"value": "margin",
83+
"message": "Verwende die 'margin' Eigenschaft",
84+
"options": { "caseSensitive": false }
85+
},
86+
{
87+
"type": "property_value",
88+
"value": { "property": "margin", "expected": "1rem" },
89+
"message": "Setze margin auf '1rem'"
90+
}
91+
]
92+
},
93+
{
94+
"id": "box-model-4",
95+
"title": "Box-Sizing: Content-Box vs. Border-Box",
96+
"description": "Die box-sizing Eigenschaft bestimmt, wie Elementdimensionen berechnet werden. 'content-box' (Standard) schließt Padding und Border aus, während 'border-box' sie einschließt.",
97+
"task": "Setze box-sizing auf 'border-box'. Dadurch werden Padding und Border in die angegebene Breite und Höhe einbezogen.",
98+
"previewHTML": "<div class=\"sizing-demo\"><div class=\"box content-box\">Content-box (Standard)</div><div class=\"box border-box\">Border-box</div></div>",
99+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .sizing-demo { display: flex; gap: 1rem; } .box { width: 200px; padding: 1rem; border: 0.25rem solid #333; background: #f5f5f5; } .content-box { box-sizing: content-box; } .border-box { /* Dein Code hier */ }",
100+
"sandboxCSS": "",
101+
"codePrefix": "/* Setze die box-sizing Eigenschaft */\n.border-box {\n /* Füge deinen Code unten ein */\n ",
102+
"initialCode": "",
103+
"codeSuffix": "\n}",
104+
"previewContainer": "preview-area",
105+
"validations": [
106+
{
107+
"type": "contains",
108+
"value": "box-sizing",
109+
"message": "Verwende die 'box-sizing' Eigenschaft",
110+
"options": { "caseSensitive": false }
111+
},
112+
{
113+
"type": "property_value",
114+
"value": { "property": "box-sizing", "expected": "border-box" },
115+
"message": "Setze box-sizing auf 'border-box'"
116+
}
117+
]
118+
},
119+
{
120+
"id": "box-model-5",
121+
"title": "Margin-Kollaps",
122+
"description": "Ein wichtiges Verhalten des Box-Modells: Wenn zwei vertikale Margins aufeinandertreffen, kollabieren sie zum größeren der beiden Werte.",
123+
"task": "Füge dem ersten Absatz einen bottom-margin von '2rem' hinzu. Der Abstand zwischen den Absätzen beträgt 2rem (nicht 3rem) - das ist Margin-Kollaps.",
124+
"previewHTML": "<div class=\"collapse-demo\"><p class=\"first\">Dieser Absatz hat einen Bottom-Margin.</p><p class=\"second\">Dieser Absatz hat einen Top-Margin von 1rem.</p></div>",
125+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .collapse-demo { border: 0.0625rem solid #ddd; padding: 0.5rem; background: #f9f9f9; } .second { margin-top: 1rem; background: #f0f0f0; }",
126+
"sandboxCSS": "",
127+
"codePrefix": "/* Füge Margin hinzu, um Margin-Kollaps zu beobachten */\n.first {\n /* Füge deinen Code unten ein */\n ",
128+
"initialCode": "",
129+
"codeSuffix": "\n}",
130+
"previewContainer": "preview-area",
131+
"validations": [
132+
{
133+
"type": "contains",
134+
"value": "margin-bottom",
135+
"message": "Verwende die 'margin-bottom' Eigenschaft",
136+
"options": { "caseSensitive": false }
137+
},
138+
{
139+
"type": "property_value",
140+
"value": { "property": "margin-bottom", "expected": "2rem" },
141+
"message": "Setze margin-bottom auf '2rem'"
142+
}
143+
]
144+
},
145+
{
146+
"id": "box-model-6",
147+
"title": "Margin-Kurzschreibweise",
148+
"description": "CSS bietet Kurzschreibweisen, um mehrere Eigenschaften gleichzeitig zu setzen. Die Margin-Kurzschreibweise setzt alle vier Seiten (oben, rechts, unten, links) im Uhrzeigersinn.",
149+
"task": "Verwende die Margin-Kurzschreibweise, um Top/Bottom auf '1rem' und Left/Right auf '2rem' zu setzen.",
150+
"previewHTML": "<div class=\"container\"><div class=\"shorthand-box\">Diese Box braucht Margins: 1rem oben/unten, 2rem links/rechts</div></div>",
151+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .container { background-color: #f5f5f5; padding: 0.5rem; } .shorthand-box { background-color: #e8f5e9; border: 0.125rem solid #66bb6a; padding: 1rem; }",
152+
"sandboxCSS": "",
153+
"codePrefix": "/* Verwende die Margin-Kurzschreibweise */\n.shorthand-box {\n /* Füge deinen Code unten ein */\n ",
154+
"initialCode": "",
155+
"codeSuffix": "\n}",
156+
"previewContainer": "preview-area",
157+
"validations": [
158+
{
159+
"type": "contains",
160+
"value": "margin",
161+
"message": "Verwende die 'margin' Eigenschaft",
162+
"options": { "caseSensitive": false }
163+
},
164+
{
165+
"type": "regex",
166+
"value": "margin:\\s*1rem\\s+2rem",
167+
"message": "Verwende 'margin: 1rem 2rem' für vertikale und horizontale Margins",
168+
"options": { "caseSensitive": false }
169+
}
170+
]
171+
},
172+
{
173+
"id": "box-model-7",
174+
"title": "Padding-Kurzschreibweise",
175+
"description": "Ähnlich wie Margin erlaubt Padding-Kurzschreibweise das Setzen aller vier Seiten. Die Syntax folgt dem gleichen Muster: oben, rechts, unten, links (TRouBLe).",
176+
"task": "Verwende Padding-Kurzschreibweise, um alle Seiten auf '1.5rem' zu setzen. Ein einzelner Wert gilt für alle vier Seiten.",
177+
"previewHTML": "<div class=\"padding-box\">Diese Box braucht gleichmäßiges Padding</div>",
178+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .padding-box { background-color: #fff3e0; border: 0.125rem solid #ff9800; }",
179+
"sandboxCSS": "",
180+
"codePrefix": "/* Verwende die Padding-Kurzschreibweise */\n.padding-box {\n /* Füge deinen Code unten ein */\n ",
181+
"initialCode": "",
182+
"codeSuffix": "\n}",
183+
"previewContainer": "preview-area",
184+
"validations": [
185+
{
186+
"type": "contains",
187+
"value": "padding",
188+
"message": "Verwende die 'padding' Eigenschaft",
189+
"options": { "caseSensitive": false }
190+
},
191+
{
192+
"type": "property_value",
193+
"value": { "property": "padding", "expected": "1.5rem" },
194+
"message": "Setze padding auf '1.5rem' für alle Seiten"
195+
}
196+
]
197+
},
198+
{
199+
"id": "box-model-8",
200+
"title": "Border-Kurzschreibweise und Einzeleigenschaften",
201+
"description": "Border-Eigenschaften können einzeln (border-width, border-style, border-color) oder als Kurzschreibweise gesetzt werden. Für noch mehr Kontrolle können einzelne Seiten angesprochen werden.",
202+
"task": "Setze nur den unteren Rahmen auf '0.25rem solid #2196f3'. Verwende border-bottom statt der allgemeinen border-Eigenschaft.",
203+
"previewHTML": "<div class=\"border-demo\">Dieses Element braucht nur einen unteren Rahmen</div>",
204+
"previewBaseCSS": "body { font-family: system-ui, -apple-system, sans-serif; padding: 1rem; } .border-demo { padding: 1rem; background-color: #e3f2fd; }",
205+
"sandboxCSS": "",
206+
"codePrefix": "/* Füge nur einen unteren Rahmen hinzu */\n.border-demo {\n /* Füge deinen Code unten ein */\n ",
207+
"initialCode": "",
208+
"codeSuffix": "\n}",
209+
"previewContainer": "preview-area",
210+
"validations": [
211+
{
212+
"type": "contains",
213+
"value": "border-bottom",
214+
"message": "Verwende die 'border-bottom' Eigenschaft",
215+
"options": { "caseSensitive": false }
216+
},
217+
{
218+
"type": "regex",
219+
"value": "border-bottom:\\s*0.25rem\\s+solid\\s+#2196f3",
220+
"message": "Setze border-bottom auf '0.25rem solid #2196f3'",
221+
"options": { "caseSensitive": false }
222+
}
223+
]
224+
}
225+
]
226+
}

lessons/de/05-units-variables.json

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{
2+
"$schema": "../../schemas/code-crispies-module-schema.json",
3+
"id": "units-variables",
4+
"title": "Einheiten, var() und calc()",
5+
"description": "Verstehe die Vielfalt der CSS-Maßeinheiten und wie du Custom Properties für wartbare Stile definierst und verwendest.",
6+
"difficulty": "beginner",
7+
"lessons": [
8+
{
9+
"id": "units-1",
10+
"title": "Absolute vs. Relative Einheiten",
11+
"description": "Lerne den Unterschied zwischen px, rem, em, % und vw/vh für flexible, responsive Layouts.",
12+
"task": "Setze die Breite von '.unit-box' auf 80% und max-width auf 37.5rem.",
13+
"previewHTML": "<div class=\"unit-box\">Ändere meine Größe!</div>",
14+
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .unit-box { background: #f5f5f5; padding: 1rem; }",
15+
"sandboxCSS": "",
16+
"codePrefix": "/* Setze flexible Größen */\n.unit-box {",
17+
"initialCode": "",
18+
"codeSuffix": "}",
19+
"previewContainer": "preview-area",
20+
"validations": [
21+
{ "type": "contains", "value": "width", "message": "Verwende die 'width' Eigenschaft", "options": { "caseSensitive": false } },
22+
{ "type": "property_value", "value": { "property": "width", "expected": "80%" }, "message": "Setze width auf '80%'" },
23+
{ "type": "contains", "value": "max-width", "message": "Verwende die 'max-width' Eigenschaft", "options": { "caseSensitive": false } },
24+
{ "type": "property_value", "value": { "property": "max-width", "expected": "37.5rem" }, "message": "Setze max-width auf '37.5rem'" }
25+
]
26+
},
27+
{
28+
"id": "units-2",
29+
"title": "CSS Custom Properties",
30+
"description": "Definiere und verwende Variablen (--custom properties) wieder, um deine Theme-Werte zu zentralisieren.",
31+
"task": "Erstelle eine <code>--main-color</code> Variable in :root mit #6200ee und wende sie als Rahmenfarbe auf '.var-box' an.",
32+
"previewHTML": "<div class=\"var-box\">Variablen-Box</div>",
33+
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .var-box { padding: 1rem; border: 0.125rem solid #ddd; }",
34+
"sandboxCSS": "",
35+
"codePrefix": "/* Definiere und verwende eine CSS-Variable */\n:root {",
36+
"initialCode": "",
37+
"codeSuffix": "}\n.var-box { }",
38+
"previewContainer": "preview-area",
39+
"validations": [
40+
{ "type": "contains", "value": "--main-color", "message": "Definiere '--main-color' in :root", "options": { "caseSensitive": false } },
41+
{ "type": "contains", "value": "var(--main-color)", "message": "Verwende var(--main-color)", "options": { "caseSensitive": false } },
42+
{
43+
"type": "property_value",
44+
"value": { "property": "border", "expected": "var(--main-color)" },
45+
"message": "Wende die Variable auf die Rahmenfarbe an",
46+
"options": { "exact": false }
47+
}
48+
]
49+
},
50+
{
51+
"id": "units-3",
52+
"title": "Einheiten-Berechnungen (calc)",
53+
"description": "Verwende die <code>calc()</code> Funktion, um verschiedene Einheiten in einem Ausdruck zu kombinieren.",
54+
"task": "Setze die Breite von '.calc-box' auf calc(100% - 2rem) und min-height auf calc(10vh + 1rem).",
55+
"previewHTML": "<div class=\"calc-box\">Calc Demo</div>",
56+
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .calc-box { background: #e8f5e9; padding: 1rem; }",
57+
"sandboxCSS": "",
58+
"codePrefix": "/* Verwende calc für dynamische Größen */\n.calc-box {",
59+
"initialCode": "",
60+
"codeSuffix": "}",
61+
"previewContainer": "preview-area",
62+
"validations": [
63+
{ "type": "contains", "value": "calc", "message": "Verwende die 'calc()' Funktion", "options": { "caseSensitive": false } },
64+
{
65+
"type": "regex",
66+
"value": "width:\\s*calc\\(100% - 2rem\\)",
67+
"message": "Width sollte calc(100% - 2rem) sein",
68+
"options": { "caseSensitive": false }
69+
},
70+
{
71+
"type": "regex",
72+
"value": "min-height:\\s*calc\\(10vh \\+ 1rem\\)",
73+
"message": "Min-height sollte calc(10vh + 1rem) sein",
74+
"options": { "caseSensitive": false }
75+
}
76+
]
77+
},
78+
{
79+
"id": "units-4",
80+
"title": "Viewport & Responsive Einheiten",
81+
"description": "Steuere Layouts relativ zur Viewport-Größe mit vw, vh und vmin/vmax Einheiten.",
82+
"task": "Gib '.viewport-box' eine Breite von 50vw und Höhe von 20vh.",
83+
"previewHTML": "<div class=\"viewport-box\">Viewport-Box</div>",
84+
"previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .viewport-box { background: #ffe0b2; }",
85+
"sandboxCSS": "",
86+
"codePrefix": "/* Verwende Viewport-Einheiten */\n.viewport-box {",
87+
"initialCode": "",
88+
"codeSuffix": "}",
89+
"previewContainer": "preview-area",
90+
"validations": [
91+
{ "type": "contains", "value": "vw", "message": "Verwende 'vw' Einheit", "options": { "caseSensitive": false } },
92+
{ "type": "contains", "value": "vh", "message": "Verwende 'vh' Einheit", "options": { "caseSensitive": false } },
93+
{ "type": "property_value", "value": { "property": "width", "expected": "50vw" }, "message": "Setze width auf '50vw'" },
94+
{ "type": "property_value", "value": { "property": "height", "expected": "20vh" }, "message": "Setze height auf '20vh'" }
95+
]
96+
}
97+
]
98+
}

0 commit comments

Comments
 (0)