New CSS Modules: - Gradients (3 lessons): linear-gradient, radial-gradient, direction - Filters (4 lessons): blur, grayscale, brightness, drop-shadow - Positioning (4 lessons): relative, absolute, offset properties - Pseudo-elements (4 lessons): ::before, ::after, content, decorative New HTML Module: - Semantic HTML (3 lessons): article, section, aside Expanded Existing Modules: - Typography: +2 lessons (text-decoration, text-shadow) - Tables: +2 lessons (thead/tbody/tfoot, colspan) Total lessons: 101 (up from ~66) - Enables full milestone system (1, 5, 10, 20, 30, 50, 75, 100) - All modules added to all 6 language stores with EN fallback
99 lines
5.3 KiB
JSON
99 lines
5.3 KiB
JSON
{
|
||
"$schema": "../schemas/code-crispies-module-schema.json",
|
||
"id": "css-positioning",
|
||
"title": "CSS Positioning",
|
||
"description": "Control element placement with CSS positioning properties.",
|
||
"difficulty": "intermediate",
|
||
"lessons": [
|
||
{
|
||
"id": "position-1",
|
||
"title": "Relative Position",
|
||
"description": "The <kbd>position</kbd> property controls how elements are placed. <kbd>relative</kbd> keeps the element in normal flow but allows you to offset it with <kbd>top</kbd>, <kbd>right</kbd>, <kbd>bottom</kbd>, <kbd>left</kbd>.<br><br><pre>.box {\n position: relative;\n top: 10px;\n}</pre>",
|
||
"task": "Make the badge position relative so we can offset it.",
|
||
"previewHTML": "<div class=\"card\"><span class=\"badge\">NEW</span><h3>Product</h3></div>",
|
||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .card { padding: 1rem; background: white; border: 2px solid #eee; border-radius: 8px; } .card h3 { margin: 0; } .badge { display: inline-block; padding: 2px 8px; background: coral; color: white; font-size: 0.7rem; font-weight: bold; border-radius: 4px; }",
|
||
"sandboxCSS": "",
|
||
"codePrefix": ".badge {\n ",
|
||
"initialCode": "",
|
||
"codeSuffix": "\n}",
|
||
"solution": "position: relative;",
|
||
"previewContainer": "preview-area",
|
||
"validations": [
|
||
{
|
||
"type": "property_value",
|
||
"value": { "property": "position", "expected": "relative" },
|
||
"message": "Set <kbd>position: relative</kbd>"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "position-2",
|
||
"title": "Offset Properties",
|
||
"description": "With <kbd>position: relative</kbd>, use offset properties to nudge the element from its original position:<br><br><kbd>top</kbd> - pushes down from top<br><kbd>left</kbd> - pushes right from left<br><br>Negative values move in the opposite direction.",
|
||
"task": "Move the badge up with <kbd>top: -8px</kbd>.",
|
||
"previewHTML": "<div class=\"card\"><span class=\"badge\">NEW</span><h3>Product</h3></div>",
|
||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .card { padding: 1rem; background: white; border: 2px solid #eee; border-radius: 8px; } .card h3 { margin: 0; } .badge { display: inline-block; padding: 2px 8px; background: coral; color: white; font-size: 0.7rem; font-weight: bold; border-radius: 4px; position: relative; }",
|
||
"sandboxCSS": "",
|
||
"codePrefix": ".badge {\n ",
|
||
"initialCode": "",
|
||
"codeSuffix": "\n}",
|
||
"solution": "top: -8px;",
|
||
"previewContainer": "preview-area",
|
||
"validations": [
|
||
{
|
||
"type": "property_value",
|
||
"value": { "property": "top", "expected": "-8px" },
|
||
"message": "Set <kbd>top: -8px</kbd>"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "position-3",
|
||
"title": "Absolute Position",
|
||
"description": "<kbd>position: absolute</kbd> removes the element from normal flow and positions it relative to its nearest positioned ancestor (or the viewport if none exists).<br><br>Always set a parent to <kbd>position: relative</kbd> to contain absolute children.",
|
||
"task": "Position the close button absolutely.",
|
||
"previewHTML": "<div class=\"modal\"><button class=\"close\">×</button><h3>Modal</h3><p>Content here</p></div>",
|
||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .modal { position: relative; padding: 2rem; background: white; border-radius: 12px; box-shadow: 0 4px 24px rgba(0,0,0,0.15); max-width: 250px; } .modal h3 { margin: 0 0 8px; } .modal p { margin: 0; color: #666; } .close { width: 32px; height: 32px; border: none; background: #f5f5f5; border-radius: 50%; font-size: 1.2rem; cursor: pointer; }",
|
||
"sandboxCSS": "",
|
||
"codePrefix": ".close {\n ",
|
||
"initialCode": "",
|
||
"codeSuffix": "\n}",
|
||
"solution": "position: absolute;",
|
||
"previewContainer": "preview-area",
|
||
"validations": [
|
||
{
|
||
"type": "property_value",
|
||
"value": { "property": "position", "expected": "absolute" },
|
||
"message": "Set <kbd>position: absolute</kbd>"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"id": "position-4",
|
||
"title": "Placing Absolute Elements",
|
||
"description": "Combine <kbd>position: absolute</kbd> with offset properties to place elements precisely.<br><br><pre>.close {\n position: absolute;\n top: 8px;\n right: 8px;\n}</pre>",
|
||
"task": "Move the close button to the top right corner with <kbd>top: 8px</kbd> and <kbd>right: 8px</kbd>.",
|
||
"previewHTML": "<div class=\"modal\"><button class=\"close\">×</button><h3>Modal</h3><p>Content here</p></div>",
|
||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .modal { position: relative; padding: 2rem; background: white; border-radius: 12px; box-shadow: 0 4px 24px rgba(0,0,0,0.15); max-width: 250px; } .modal h3 { margin: 0 0 8px; } .modal p { margin: 0; color: #666; } .close { position: absolute; width: 32px; height: 32px; border: none; background: #f5f5f5; border-radius: 50%; font-size: 1.2rem; cursor: pointer; }",
|
||
"sandboxCSS": "",
|
||
"codePrefix": ".close {\n ",
|
||
"initialCode": "",
|
||
"codeSuffix": "\n}",
|
||
"solution": "top: 8px;\n right: 8px;",
|
||
"previewContainer": "preview-area",
|
||
"validations": [
|
||
{
|
||
"type": "property_value",
|
||
"value": { "property": "top", "expected": "8px" },
|
||
"message": "Set <kbd>top: 8px</kbd>"
|
||
},
|
||
{
|
||
"type": "property_value",
|
||
"value": { "property": "right", "expected": "8px" },
|
||
"message": "Set <kbd>right: 8px</kbd>"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|