Files
code-crispies/lessons/05-units-variables.json
Michael Czechowski c560676544 feat: implement #4 — replace answer-revealing validation messages with pedagogical hints
Rewrite ~120 validation error messages across 17 English lesson modules
and their localized variants (ar, de, es, pl, uk) to use concept questions,
property hints, and directional nudges instead of revealing the exact
CSS property-value answers.

Priority modules (flexbox, box-model, colors, positioning) fully rewritten.
All remaining CSS modules updated. Only message strings changed — no
validation logic modifications.
2026-03-28 19:40:28 +01:00

102 lines
6.4 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"$schema": "../schemas/code-crispies-module-schema.json",
"id": "units-variables",
"title": "CSS Units & Variables",
"description": "Understand the variety of CSS measurement units and how to define and use custom properties for maintainable styles.",
"difficulty": "beginner",
"lessons": [
{
"id": "units-1",
"title": "Relative Units",
"description": "CSS offers two types of units: <em>absolute</em> (like <kbd>px</kbd>) and <em>relative</em> (like <kbd>%</kbd> and <kbd>rem</kbd>). Relative units adapt to their context, making layouts flexible and accessible.<br><br><strong>Common relative units:</strong><br>• <kbd>%</kbd> Relative to parent element<br>• <kbd>rem</kbd> Relative to root font size (typically 16px)<br>• <kbd>em</kbd> Relative to element's font size<br><br>A common pattern for readable content: set <kbd>width: 100%</kbd> so it fills available space, then <kbd>max-width: 40rem</kbd> to cap line length for readability.",
"task": "This article text runs too wide on large screens. Add <kbd>max-width: 40rem</kbd> to <kbd>.article</kbd> for optimal reading width.",
"previewHTML": "<article class=\"article\"><h2>The Art of Typography</h2><p>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.</p><p>The ideal line length is 45-75 characters per line. At typical font sizes, this works out to roughly 40rem maximum width.</p></article>",
"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": "Which property caps an element's width? Try a <kbd>rem</kbd> value for readable line length."
}
]
},
{
"id": "units-2",
"title": "CSS Variables",
"description": "CSS custom properties (variables) let you define reusable values. Define them with <kbd>--name</kbd> and use them with <kbd>var(--name)</kbd>. Variables defined on <kbd>:root</kbd> are available everywhere.",
"task": "Define <kbd>--brand: steelblue</kbd> in <kbd>:root</kbd>, then use it as the <kbd>background</kbd> color for <kbd>.btn</kbd>.",
"previewHTML": "<div class=\"actions\"><button class=\"btn\">Subscribe</button><button class=\"btn\">Learn More</button></div>",
"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": "Define <kbd>--brand</kbd> variable",
"options": { "caseSensitive": false }
},
{
"type": "contains",
"value": "steelblue",
"message": "Set the value to <kbd>steelblue</kbd>",
"options": { "caseSensitive": false }
}
]
},
{
"id": "units-3",
"title": "calc() Function",
"description": "The <kbd>calc()</kbd> function lets you mix different units in calculations. This is essential for layouts that combine fixed and flexible sizing, like a sidebar layout.",
"task": "The main content should fill the remaining space after the 200px sidebar. Set <kbd>width: calc(100% - 200px)</kbd> on <kbd>.main</kbd>.",
"previewHTML": "<div class=\"layout\"><aside class=\"sidebar\">Sidebar<br>Navigation</aside><main class=\"main\"><h2>Main Content</h2><p>This area should fill the remaining width after accounting for the fixed-width sidebar.</p></main></div>",
"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": "Use <kbd>calc()</kbd> to subtract the sidebar's fixed width from the full container width.",
"options": { "caseSensitive": false }
}
]
},
{
"id": "units-4",
"title": "Viewport Units",
"description": "Viewport units size elements relative to the browser window:<br>• <kbd>vw</kbd> 1% of viewport width<br>• <kbd>vh</kbd> 1% of viewport height<br><br>These are perfect for full-screen sections like hero banners.",
"task": "Make this hero section fill the viewport height by setting <kbd>min-height: 100vh</kbd> on <kbd>.hero</kbd>.",
"previewHTML": "<section class=\"hero\"><h1>Welcome</h1><p>Scroll down to explore</p></section>",
"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": "Which property ensures a minimum height? Use a viewport unit for full-screen coverage."
}
]
}
]
}