Files
code-crispies/lessons/uk/flexbox.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

136 lines
11 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": "flexbox",
"title": "CSS Flexbox",
"description": "Опануйте модель гнучкого блочного макету для сучасних адаптивних дизайнів",
"difficulty": "intermediate",
"lessons": [
{
"id": "flexbox-1",
"title": "Container",
"description": "До flexbox навіть прості макети вимагали floats, хаків позиціонування або табличних макетів. Flexbox (Flexible Box Layout) революціонізував CSS, надавши одновимірну систему макетування, спеціально розроблену для розподілу простору та вирівнювання вмісту.<br><br><strong>Як це працює:</strong> Коли ви встановлюєте <kbd>display: flex</kbd> на елемент, він стає <em>flex-контейнером</em>. Його прямі нащадки автоматично стають <em>flex-елементами</em>, що розташовуються вздовж головної осі (горизонтально за замовчуванням). Ця одна властивість перетворює вкладені блокові елементи в горизонтальний ряд.<br><br><strong>Дві осі:</strong><br>• <em>Головна вісь</em> Основний напрямок потоку елементів (row = зліва→направо)<br>• <em>Поперечна вісь</em> Перпендикулярна до головної (row = зверху→вниз)<br><br><pre>.nav {\n display: flex;\n}</pre>",
"task": "Це навігаційне меню розташовується вертикально. Додайте <kbd>display: flex</kbd>, щоб розташувати посилання горизонтально.",
"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;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "display", "expected": "flex" },
"message": "Яке значення display перетворює елемент на гнучкий контейнер?"
}
]
},
{
"id": "flexbox-2",
"title": "Gap",
"description": "Властивість <kbd>gap</kbd> додає послідовний відступ між flex-елементами без потреби у відступах (margins). Вона створює простір лише між елементами, а не по краях.",
"task": "Додайте <kbd>gap: 1rem</kbd>, щоб рівномірно розташувати навігаційні посилання.",
"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": "gap: 1rem;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "gap", "expected": "1rem" },
"message": "Яка властивість створює відстань між flex-елементами без використання margin?"
}
]
},
{
"id": "flexbox-3",
"title": "Justify Content",
"description": "<kbd>justify-content</kbd> розподіляє елементи вздовж головної осі. Поширені значення:<br>• <kbd>flex-start</kbd> групувати на початку<br>• <kbd>flex-end</kbd> групувати в кінці<br>• <kbd>center</kbd> центрувати елементи<br>• <kbd>space-between</kbd> рівний простір між елементами<br>• <kbd>space-around</kbd> рівний простір навколо елементів",
"task": "Перемістіть кнопку \"Login\" праворуч, встановивши <kbd>justify-content: space-between</kbd> на навігації.",
"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;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "justify-content", "expected": "space-between" },
"message": "Яке значення <kbd>justify-content</kbd> розміщує перший та останній елементи на протилежних краях?"
}
]
},
{
"id": "flexbox-4",
"title": "Align Items",
"description": "<kbd>align-items</kbd> керує вирівнюванням по поперечній осі (вертикально, коли flex-direction це row). Значення включають:<br>• <kbd>stretch</kbd> розтягнути для заповнення (за замовчуванням)<br>• <kbd>flex-start</kbd> вирівняти вгору<br>• <kbd>flex-end</kbd> вирівняти вниз<br>• <kbd>center</kbd> центрувати вертикально",
"task": "Логотип та навігаційні посилання мають різну висоту. Відцентруйте їх вертикально за допомогою <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;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "align-items", "expected": "center" },
"message": "Яка властивість вирівнює flex-елементи вздовж поперечної осі?"
}
]
},
{
"id": "flexbox-5",
"title": "Flex Wrap",
"description": "За замовчуванням flex-елементи стискаються в один рядок. <kbd>flex-wrap: wrap</kbd> дозволяє елементам переходити на кілька рядків, коли місця недостатньо.",
"task": "Ці картки виходять за межі контейнера. Додайте <kbd>flex-wrap: wrap</kbd>, щоб дозволити їм переходити на нові рядки.",
"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-wrap: wrap;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "flex-wrap", "expected": "wrap" },
"message": "Яка властивість дозволяє flex-елементам переходити на кілька рядків?"
}
]
},
{
"id": "flexbox-6",
"title": "Flex Grow",
"description": "Властивість <kbd>flex</kbd> на елементах керує тим, як вони ростуть і зменшуються. <kbd>flex: 1</kbd> змушує елемент рости, щоб заповнити доступний простір. Кілька елементів з <kbd>flex: 1</kbd> ділять простір порівну.",
"task": "Зробіть так, щоб поле пошуку розширилось і заповнило доступний простір, встановивши <kbd>flex: 1</kbd> на <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": "flex: 1;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "flex", "expected": "1" },
"message": "Яка властивість змушує flex-елемент зростати, щоб заповнити залишковий простір?"
}
]
}
]
}