Files
code-crispies/lessons/05-units-variables.json
Michael Czechowski bd3f9ab96a refactor: rewrite CSS lessons with realistic real-world examples
- Box Model: profile cards, alerts, buttons instead of generic boxes
- Flexbox: navigation bars, headers, toolbars, card layouts
- Grid: photo gallery with SVG images, product cards, dashboard layout
- Colors: notification alerts, buttons, badges with visible changes
- Units/Variables: article width, brand variables, sidebar calc, hero vh
- Responsive: feature cards grid instead of numbered divs
- Added missing solutions to enable "Show Expected" feature
- Fixed barely visible border color change in colors lesson

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-01-13 21:11:41 +01:00

102 lines
6.3 KiB
JSON
Raw 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": "Set <kbd>max-width: 40rem</kbd>"
}
]
},
{
"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": "Set <kbd>width: calc(100% - 200px)</kbd>",
"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": "Set <kbd>min-height: 100vh</kbd>"
}
]
}
]
}