{ "$schema": "../../schemas/code-crispies-module-schema.json", "id": "units-variables", "title": "CSS Einheiten & Variablen", "description": "Verstehe die Vielfalt der CSS-Maßeinheiten und wie du Custom Properties für wartbare Stile definierst und verwendest.", "difficulty": "beginner", "lessons": [ { "id": "units-1", "title": "Relative Units", "description": "CSS bietet zwei Arten von Einheiten: absolute (wie px) und relative (wie % und rem). Relative Einheiten passen sich ihrem Kontext an und machen Layouts flexibel und zugänglich.

Häufige relative Einheiten:
% – Relativ zum Elternelement
rem – Relativ zur Root-Schriftgröße (typisch 16px)
em – Relativ zur Schriftgröße des Elements

Ein häufiges Muster für lesbaren Inhalt: setze width: 100%, damit es den verfügbaren Platz füllt, dann max-width: 40rem um die Zeilenlänge für Lesbarkeit zu begrenzen.", "task": "Dieser Artikeltext läuft auf großen Bildschirmen zu breit. Füge max-width: 40rem hinzu für optimale Lesebreite.", "previewHTML": "

The Art of Typography

Good typography is invisible. When text is set well, readers absorb information without noticing the design decisions that make it comfortable to read. Line length is crucial—too wide and eyes get lost, too narrow and reading becomes choppy.

The ideal line length is 45-75 characters per line. At typical font sizes, this works out to roughly 40rem maximum width.

", "previewBaseCSS": "body { font-family: Georgia, serif; padding: 1rem; background: #f9f9f9; } .article { background: white; padding: 2rem; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .article h2 { margin: 0 0 1rem; color: #333; } .article p { margin: 0 0 1rem; line-height: 1.6; color: #444; } .article p:last-child { margin-bottom: 0; }", "sandboxCSS": "", "codePrefix": ".article {\n ", "initialCode": "", "codeSuffix": "\n}", "solution": "max-width: 40rem;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", "value": { "property": "max-width", "expected": "40rem" }, "message": "Setze max-width: 40rem" } ] }, { "id": "units-2", "title": "CSS Variables", "description": "CSS Custom Properties (Variablen) erlauben dir, wiederverwendbare Werte zu definieren. Definiere sie mit --name und verwende sie mit var(--name). Variablen auf :root sind überall verfügbar.", "task": "Definiere --brand: steelblue in :root, dann verwende es als background-Farbe für .btn.", "previewHTML": "
", "previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .actions { display: flex; gap: 1rem; } .btn { color: white; border: none; padding: 12px 24px; border-radius: 6px; font-size: 1rem; cursor: pointer; background: #ccc; }", "sandboxCSS": "", "codePrefix": ":root {\n ", "initialCode": "", "codeSuffix": "\n}\n\n.btn {\n background: var(--brand);\n}", "solution": "--brand: steelblue;", "previewContainer": "preview-area", "validations": [ { "type": "contains", "value": "--brand", "message": "Definiere die --brand Variable", "options": { "caseSensitive": false } }, { "type": "contains", "value": "steelblue", "message": "Setze den Wert auf steelblue", "options": { "caseSensitive": false } } ] }, { "id": "units-3", "title": "calc() Function", "description": "Die calc() Funktion ermöglicht das Mischen verschiedener Einheiten in Berechnungen. Das ist essenziell für Layouts, die feste und flexible Größen kombinieren, wie ein Sidebar-Layout.", "task": "Der Hauptinhalt soll den verbleibenden Platz nach der 200px Sidebar füllen. Setze width: calc(100% - 200px) auf .main.", "previewHTML": "

Main Content

This area should fill the remaining width after accounting for the fixed-width sidebar.

", "previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .layout { display: flex; gap: 1rem; } .sidebar { width: 200px; background: #1a1a2e; color: white; padding: 1rem; border-radius: 8px; flex-shrink: 0; } .main { background: white; padding: 1rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .main h2 { margin: 0 0 8px; } .main p { margin: 0; color: #666; }", "sandboxCSS": "", "codePrefix": ".main {\n ", "initialCode": "", "codeSuffix": "\n}", "solution": "width: calc(100% - 200px);", "previewContainer": "preview-area", "validations": [ { "type": "regex", "value": "width:\\s*calc\\(\\s*100%\\s*-\\s*200px\\s*\\)", "message": "Setze width: calc(100% - 200px)", "options": { "caseSensitive": false } } ] }, { "id": "units-4", "title": "Viewport Units", "description": "Viewport-Einheiten dimensionieren Elemente relativ zum Browserfenster:
vw – 1% der Viewport-Breite
vh – 1% der Viewport-Höhe

Diese sind perfekt für Vollbild-Sektionen wie Hero-Banner.", "task": "Mache diese Hero-Sektion so hoch wie das Viewport mit min-height: 100vh.", "previewHTML": "

Welcome

Scroll down to explore

", "previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .hero { background: linear-gradient(135deg, #1a1a2e 0%, steelblue 100%); color: white; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 2rem; } .hero h1 { margin: 0 0 1rem; font-size: 2.5rem; } .hero p { margin: 0; opacity: 0.8; }", "sandboxCSS": "", "codePrefix": ".hero {\n ", "initialCode": "", "codeSuffix": "\n}", "solution": "min-height: 100vh;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", "value": { "property": "min-height", "expected": "100vh" }, "message": "Setze min-height: 100vh" } ] } ] }