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)
This commit is contained in:
@@ -8,12 +8,12 @@
|
||||
{
|
||||
"id": "flexbox-1",
|
||||
"title": "Container",
|
||||
"description": "Before flexbox, creating even simple layouts required floats, positioning hacks, or table-based layouts. Flexbox (Flexible Box Layout) revolutionized CSS by providing a one-dimensional layout system designed specifically for distributing space and aligning content.<br><br><strong>How it works:</strong> When you set <kbd>display: flex</kbd> on an element, it becomes a <em>flex container</em>. Its direct children automatically become <em>flex items</em> that flow along a main axis (horizontal by default). This single property transforms stacked block elements into a horizontal row.<br><br><strong>The two axes:</strong><br>• <em>Main axis</em> – The primary direction items flow (row = left→right)<br>• <em>Cross axis</em> – Perpendicular to main (row = top→bottom)<br><br><pre>.container {\n display: flex;\n /* Items now flow horizontally */\n}</pre>",
|
||||
"task": "Add <kbd>display: flex</kbd> to <kbd>.wrap</kbd> to arrange the boxes horizontally.",
|
||||
"previewHTML": "<div class='wrap'><div class='box'>1</div><div class='box'>2</div><div class='box'>3</div></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .box { background: steelblue; color: white; padding: 1rem; margin: 8px; text-align: center; font-weight: bold; }",
|
||||
"sandboxCSS": ".wrap { border: 2px dashed #aaa; padding: 1rem; }",
|
||||
"codePrefix": ".wrap {\n ",
|
||||
"description": "Before flexbox, creating even simple layouts required floats, positioning hacks, or table-based layouts. Flexbox (Flexible Box Layout) revolutionized CSS by providing a one-dimensional layout system designed specifically for distributing space and aligning content.<br><br><strong>How it works:</strong> When you set <kbd>display: flex</kbd> on an element, it becomes a <em>flex container</em>. Its direct children automatically become <em>flex items</em> that flow along a main axis (horizontal by default). This single property transforms stacked block elements into a horizontal row.<br><br><strong>The two axes:</strong><br>• <em>Main axis</em> – The primary direction items flow (row = left→right)<br>• <em>Cross axis</em> – Perpendicular to main (row = top→bottom)<br><br><pre>.nav {\n display: flex;\n}</pre>",
|
||||
"task": "This navigation menu stacks vertically. Add <kbd>display: flex</kbd> to <kbd>.nav</kbd> to arrange the links horizontally.",
|
||||
"previewHTML": "<nav class=\"nav\"><a href=\"#\">Home</a><a href=\"#\">Products</a><a href=\"#\">About</a><a href=\"#\">Contact</a></nav>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .nav { background: #1a1a2e; padding: 1rem; } .nav a { color: white; text-decoration: none; padding: 8px 1rem; border-radius: 4px; } .nav a:hover { background: rgba(255,255,255,0.1); }",
|
||||
"sandboxCSS": "",
|
||||
"codePrefix": ".nav {\n ",
|
||||
"initialCode": "",
|
||||
"codeSuffix": "\n}",
|
||||
"solution": "display: flex;",
|
||||
@@ -21,61 +21,41 @@
|
||||
"validations": [
|
||||
{
|
||||
"type": "property_value",
|
||||
"value": {
|
||||
"property": "display",
|
||||
"expected": "flex"
|
||||
},
|
||||
"value": { "property": "display", "expected": "flex" },
|
||||
"message": "Set <kbd>display: flex</kbd>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flexbox-2",
|
||||
"title": "Direction & Wrap",
|
||||
"description": "Control the direction and wrapping of flex items within a container.",
|
||||
"task": "Add <kbd>flex-direction: column</kbd> and <kbd>flex-wrap: wrap</kbd> to <kbd>.wrap</kbd>.",
|
||||
"previewHTML": "<div class='wrap'><div class='box'>1</div><div class='box'>2</div><div class='box'>3</div><div class='box'>4</div><div class='box'>5</div></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .box { background: steelblue; color: white; padding: 1rem; margin: 8px; text-align: center; font-weight: bold; width: 3rem; height: 3rem; display: flex; align-items: center; justify-content: center; }",
|
||||
"sandboxCSS": ".wrap { border: 2px dashed #aaa; padding: 1rem; height: 16rem; display: flex; }",
|
||||
"codePrefix": ".wrap {\n ",
|
||||
"title": "Gap",
|
||||
"description": "The <kbd>gap</kbd> property adds consistent spacing between flex items without needing margins. It only creates space between items, not around the edges.",
|
||||
"task": "Add <kbd>gap: 1rem</kbd> to space out the navigation links evenly.",
|
||||
"previewHTML": "<nav class=\"nav\"><a href=\"#\">Home</a><a href=\"#\">Products</a><a href=\"#\">About</a><a href=\"#\">Contact</a></nav>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .nav { background: #1a1a2e; padding: 1rem; display: flex; } .nav a { color: white; text-decoration: none; padding: 8px 1rem; border-radius: 4px; background: rgba(255,255,255,0.1); }",
|
||||
"sandboxCSS": "",
|
||||
"codePrefix": ".nav {\n ",
|
||||
"initialCode": "",
|
||||
"codeSuffix": "\n}",
|
||||
"solution": "flex-direction: column;\n flex-wrap: wrap;",
|
||||
"solution": "gap: 1rem;",
|
||||
"previewContainer": "preview-area",
|
||||
"validations": [
|
||||
{
|
||||
"type": "property_value",
|
||||
"value": {
|
||||
"property": "flex-direction",
|
||||
"expected": "column"
|
||||
},
|
||||
"message": "Set <kbd>flex-direction: column</kbd>",
|
||||
"options": {
|
||||
"exact": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "property_value",
|
||||
"value": {
|
||||
"property": "flex-wrap",
|
||||
"expected": "wrap"
|
||||
},
|
||||
"message": "Set <kbd>flex-wrap: wrap</kbd>",
|
||||
"options": {
|
||||
"exact": true
|
||||
}
|
||||
"value": { "property": "gap", "expected": "1rem" },
|
||||
"message": "Set <kbd>gap: 1rem</kbd>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flexbox-3",
|
||||
"title": "Justify Content",
|
||||
"description": "Learn how to align flex items along the main axis of the flex container.",
|
||||
"task": "Add <kbd>justify-content: space-between</kbd> to <kbd>.wrap</kbd> to distribute the boxes evenly.",
|
||||
"previewHTML": "<div class='wrap'><div class='box'>1</div><div class='box'>2</div><div class='box'>3</div></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .box { background: steelblue; color: white; padding: 1rem; text-align: center; font-weight: bold; width: 3rem; height: 3rem; display: flex; align-items: center; justify-content: center; }",
|
||||
"sandboxCSS": ".wrap { border: 2px dashed #aaa; padding: 1rem; display: flex; }",
|
||||
"codePrefix": ".wrap {\n ",
|
||||
"description": "<kbd>justify-content</kbd> distributes items along the main axis. Common values:<br>• <kbd>flex-start</kbd> – pack items at the start<br>• <kbd>flex-end</kbd> – pack at the end<br>• <kbd>center</kbd> – center items<br>• <kbd>space-between</kbd> – equal space between items<br>• <kbd>space-around</kbd> – equal space around items",
|
||||
"task": "Push the \"Login\" button to the right by setting <kbd>justify-content: space-between</kbd> on the nav.",
|
||||
"previewHTML": "<nav class=\"nav\"><div class=\"links\"><a href=\"#\">Home</a><a href=\"#\">Products</a><a href=\"#\">About</a></div><a href=\"#\" class=\"login\">Login</a></nav>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .nav { background: #1a1a2e; padding: 1rem; display: flex; } .links { display: flex; gap: 8px; } .nav a { color: white; text-decoration: none; padding: 8px 1rem; border-radius: 4px; } .nav a:hover { background: rgba(255,255,255,0.1); } .login { background: steelblue; }",
|
||||
"sandboxCSS": "",
|
||||
"codePrefix": ".nav {\n ",
|
||||
"initialCode": "",
|
||||
"codeSuffix": "\n}",
|
||||
"solution": "justify-content: space-between;",
|
||||
@@ -83,26 +63,20 @@
|
||||
"validations": [
|
||||
{
|
||||
"type": "property_value",
|
||||
"value": {
|
||||
"property": "justify-content",
|
||||
"expected": "space-between"
|
||||
},
|
||||
"message": "Set <kbd>justify-content: space-between</kbd>",
|
||||
"options": {
|
||||
"exact": true
|
||||
}
|
||||
"value": { "property": "justify-content", "expected": "space-between" },
|
||||
"message": "Set <kbd>justify-content: space-between</kbd>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flexbox-4",
|
||||
"title": "Align Items",
|
||||
"description": "Control how flex items are aligned along the cross axis of the flex container.",
|
||||
"task": "Add <kbd>align-items: center</kbd> to <kbd>.wrap</kbd> to vertically center the boxes.",
|
||||
"previewHTML": "<div class='wrap'><div class='box tall'>1</div><div class='box'>2</div><div class='box short'>3</div></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .box { background: steelblue; color: white; padding: 1rem; margin: 8px; text-align: center; font-weight: bold; width: 3rem; display: flex; justify-content: center; } .tall { height: 6rem; } .short { height: 3rem; }",
|
||||
"sandboxCSS": ".wrap { border: 2px dashed #aaa; padding: 1rem; display: flex; height: 10rem; }",
|
||||
"codePrefix": ".wrap {\n ",
|
||||
"description": "<kbd>align-items</kbd> controls alignment on the cross axis (vertical when flex-direction is row). Values include:<br>• <kbd>stretch</kbd> – stretch to fill (default)<br>• <kbd>flex-start</kbd> – align to top<br>• <kbd>flex-end</kbd> – align to bottom<br>• <kbd>center</kbd> – center vertically",
|
||||
"task": "The logo and nav links have different heights. Center them vertically with <kbd>align-items: center</kbd>.",
|
||||
"previewHTML": "<header class=\"header\"><div class=\"logo\">ACME</div><nav><a href=\"#\">Products</a><a href=\"#\">Pricing</a><a href=\"#\">Docs</a></nav></header>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .header { background: white; padding: 1rem 2rem; display: flex; justify-content: space-between; border-bottom: 1px solid #eee; } .logo { font-size: 1.5rem; font-weight: bold; color: steelblue; } nav { display: flex; gap: 1rem; } nav a { color: #333; text-decoration: none; font-size: 0.9rem; }",
|
||||
"sandboxCSS": "",
|
||||
"codePrefix": ".header {\n ",
|
||||
"initialCode": "",
|
||||
"codeSuffix": "\n}",
|
||||
"solution": "align-items: center;",
|
||||
@@ -110,62 +84,50 @@
|
||||
"validations": [
|
||||
{
|
||||
"type": "property_value",
|
||||
"value": {
|
||||
"property": "align-items",
|
||||
"expected": "center"
|
||||
},
|
||||
"message": "Set <kbd>align-items: center</kbd>",
|
||||
"options": {
|
||||
"exact": true
|
||||
}
|
||||
"value": { "property": "align-items", "expected": "center" },
|
||||
"message": "Set <kbd>align-items: center</kbd>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flexbox-5",
|
||||
"title": "Flex Grow",
|
||||
"description": "The <kbd>flex</kbd> property controls how much an item grows relative to others.",
|
||||
"task": "Add <kbd>flex: 2</kbd> to <kbd>.box2</kbd> to make it grow twice as wide.",
|
||||
"previewHTML": "<div class='wrap'><div class='box box1'>1</div><div class='box box2'>2</div><div class='box box3'>3</div></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .box { color: white; padding: 1rem; margin: 8px; text-align: center; font-weight: bold; display: flex; align-items: center; justify-content: center; } .box1 { background: coral; flex: 1; } .box2 { background: mediumseagreen; } .box3 { background: gold; flex: 1; }",
|
||||
"sandboxCSS": ".wrap { border: 2px dashed #aaa; padding: 1rem; display: flex; }",
|
||||
"codePrefix": ".box2 {\n ",
|
||||
"title": "Flex Wrap",
|
||||
"description": "By default, flex items squeeze onto one line. <kbd>flex-wrap: wrap</kbd> allows items to flow onto multiple lines when they run out of space.",
|
||||
"task": "These cards overflow the container. Add <kbd>flex-wrap: wrap</kbd> to allow them to wrap to new rows.",
|
||||
"previewHTML": "<div class=\"cards\"><article class=\"card\">Card 1</article><article class=\"card\">Card 2</article><article class=\"card\">Card 3</article><article class=\"card\">Card 4</article><article class=\"card\">Card 5</article><article class=\"card\">Card 6</article></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; background: #f5f5f5; } .cards { display: flex; gap: 1rem; } .card { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); min-width: 120px; text-align: center; }",
|
||||
"sandboxCSS": "",
|
||||
"codePrefix": ".cards {\n ",
|
||||
"initialCode": "",
|
||||
"codeSuffix": "\n}",
|
||||
"solution": "flex: 2;",
|
||||
"solution": "flex-wrap: wrap;",
|
||||
"previewContainer": "preview-area",
|
||||
"validations": [
|
||||
{
|
||||
"type": "property_value",
|
||||
"value": {
|
||||
"property": "flex",
|
||||
"expected": "2"
|
||||
},
|
||||
"message": "Set <kbd>flex: 2</kbd>"
|
||||
"value": { "property": "flex-wrap", "expected": "wrap" },
|
||||
"message": "Set <kbd>flex-wrap: wrap</kbd>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "flexbox-6",
|
||||
"title": "Align Self",
|
||||
"description": "Use <kbd>align-self</kbd> to override alignment for a single flex item.",
|
||||
"task": "Add <kbd>align-self: flex-start</kbd> to <kbd>.middle</kbd> to move it to the top.",
|
||||
"previewHTML": "<div class='wrap'><div class='box'>1</div><div class='box middle'>2</div><div class='box'>3</div></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .box { background: steelblue; color: white; padding: 1rem; margin: 8px; text-align: center; font-weight: bold; width: 3rem; height: 3rem; display: flex; align-items: center; justify-content: center; } .middle { background: mediumseagreen; }",
|
||||
"sandboxCSS": ".wrap { border: 2px dashed #aaa; padding: 1rem; display: flex; height: 12rem; align-items: center; }",
|
||||
"codePrefix": ".middle {\n ",
|
||||
"title": "Flex Grow",
|
||||
"description": "The <kbd>flex</kbd> property on items controls how they grow and shrink. <kbd>flex: 1</kbd> makes an item grow to fill available space. Multiple items with <kbd>flex: 1</kbd> share space equally.",
|
||||
"task": "Make the search input expand to fill available space by setting <kbd>flex: 1</kbd> on <kbd>.search</kbd>.",
|
||||
"previewHTML": "<div class=\"toolbar\"><input class=\"search\" type=\"text\" placeholder=\"Search...\"><button class=\"btn\">Search</button><button class=\"btn\">Filters</button></div>",
|
||||
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .toolbar { display: flex; gap: 8px; padding: 1rem; background: #f5f5f5; border-radius: 8px; } .search { padding: 8px 1rem; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem; } .btn { padding: 8px 1rem; background: steelblue; color: white; border: none; border-radius: 4px; cursor: pointer; }",
|
||||
"sandboxCSS": "",
|
||||
"codePrefix": ".search {\n ",
|
||||
"initialCode": "",
|
||||
"codeSuffix": "\n}",
|
||||
"solution": "align-self: flex-start;",
|
||||
"solution": "flex: 1;",
|
||||
"previewContainer": "preview-area",
|
||||
"validations": [
|
||||
{
|
||||
"type": "property_value",
|
||||
"value": {
|
||||
"property": "align-self",
|
||||
"expected": "flex-start"
|
||||
},
|
||||
"message": "Set <kbd>align-self: flex-start</kbd>"
|
||||
"value": { "property": "flex", "expected": "1" },
|
||||
"message": "Set <kbd>flex: 1</kbd>"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user