Files
code-crispies/lessons/pl/00-basic-selectors.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

260 lines
14 KiB
JSON

{
"$schema": "../../schemas/code-crispies-module-schema.json",
"id": "css-basic-selectors",
"title": "Podstawy CSS",
"description": "Poznaj podstawowe elementy CSS: właściwości, wartości i selektory. Ten moduł uczy zasad składni, których przestrzega każda deklaracja CSS.",
"difficulty": "beginner",
"lessons": [
{
"id": "css-properties",
"title": "Właściwości CSS",
"description": "CSS stylizuje elementy za pomocą <strong>deklaracji</strong> - par właściwości i wartości. Każda deklaracja ma ten sam wzorzec:<br><br><pre>property: value;</pre><br><strong>Właściwość</strong> to co chcesz zmienić (jak <kbd>color</kbd> lub <kbd>background</kbd>). <strong>Wartość</strong> to na co to ustawiasz. Dwukropek je rozdziela, a średnik kończy linię.<br><br>Wartości występują w różnych typach:<br>• <strong>Słowa kluczowe:</strong> <kbd>red</kbd>, <kbd>bold</kbd>, <kbd>center</kbd><br>• <strong>Liczby z jednostkami:</strong> <kbd>16px</kbd>, <kbd>2rem</kbd>, <kbd>100%</kbd><br>• <strong>Kolory:</strong> <kbd>steelblue</kbd>, <kbd>#ff0000</kbd>",
"task": "Uzupełnij deklarację dodając <kbd>color: coral;</kbd> aby zmienić kolor tekstu.",
"previewHTML": "<p class=\"text\">This text should turn coral.</p>",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } .text { font-size: 1.25rem; }",
"sandboxCSS": "",
"codePrefix": ".text {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"previewContainer": "preview-area",
"solution": "color: coral;",
"validations": [
{
"type": "property_value",
"value": { "property": "color", "expected": "coral" },
"message": "Która właściwość kontroluje kolor tekstu?"
}
]
},
{
"id": "multiple-properties",
"title": "Wiele właściwości",
"description": "Reguła może mieć wiele deklaracji. Każda idzie w osobnej linii i każda potrzebuje średnika na końcu:<br><br><pre>.box {<br> background: gold;<br> color: navy;<br> padding: 1rem;<br>}</pre><br>Kolejność zwykle nie ma znaczenia - CSS stosuje wszystkie. Przy konfliktach wygrywa ostatnia.",
"task": "Dodaj dwie deklaracje: <kbd>background: lavender;</kbd> i <kbd>padding: 1rem;</kbd>",
"previewHTML": "<div class=\"card\">A styled card with background and padding.</div>",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } .card { border-radius: 8px; }",
"sandboxCSS": "",
"codePrefix": ".card {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"previewContainer": "preview-area",
"solution": "background: lavender;\n padding: 1rem;",
"validations": [
{
"type": "property_value",
"value": { "property": "background", "expected": "lavender" },
"message": "Sprawdź właściwość <kbd>background</kbd> — jaki kolor potrzebuje karta?"
},
{
"type": "property_value",
"value": { "property": "padding", "expected": "1rem" },
"message": "Element potrzebuje wewnętrznej przestrzeni — sprawdź właściwość <kbd>padding</kbd>"
}
]
},
{
"id": "type-selectors",
"title": "Selektory typu",
"description": "<strong>Selektor</strong> mówi przeglądarce, które elementy stylizować. Najprostszym selektorem jest <strong>selektor typu</strong> — po prostu nazwa tagu HTML.<br><br><pre>p {<br> color: steelblue;<br>}</pre><br>Ta reguła celuje w każdy element <kbd>&lt;p&gt;</kbd> na stronie. Selektory typu świetnie nadają się do ustawiania podstawowych stylów.",
"task": "Ostyluj wszystkie akapity. Napisz regułę z <kbd>p</kbd> jako selektorem i ustaw <kbd>color: steelblue</kbd>.",
"previewHTML": "<article>\n <h2>Fresh Roasted Coffee</h2>\n <p>Our beans are sourced from small farms in Colombia and Ethiopia.</p>\n <p>Each batch is roasted weekly to ensure peak freshness.</p>\n</article>",
"previewBaseCSS": "body { font-family: system-ui; padding: 1rem; } h2 { margin: 0 0 1rem; }",
"sandboxCSS": "",
"codePrefix": "",
"initialCode": "",
"codeSuffix": "",
"previewContainer": "preview-area",
"solution": "p {\n color: steelblue;\n}",
"validations": [
{
"type": "regex",
"value": "p\\s*\\{",
"message": "Zacznij od <kbd>p {</kbd> aby wybrać akapity"
},
{
"type": "property_value",
"value": { "property": "color", "expected": "steelblue" },
"message": "Która właściwość kontroluje kolor tekstu?"
}
]
},
{
"id": "styling-links",
"title": "Stylizowanie linków",
"description": "Selektory typu działają dla każdego elementu HTML. Selektor <kbd>a</kbd> celuje we wszystkie linki na stronie.<br><br>Linki domyślnie mają niebieski kolor i podkreślenie. Możesz zmienić oba z CSS — użyj <kbd>color</kbd> dla tekstu i <kbd>text-decoration: none</kbd> aby usunąć podkreślenie.",
"task": "Ostyluj linki nawigacji. Napisz regułę z <kbd>a</kbd> jako selektorem i ustaw <kbd>color: coral</kbd>.",
"previewHTML": "<nav>\n <a href=\"#\">Home</a>\n <a href=\"#\">Menu</a>\n <a href=\"#\">About</a>\n <a href=\"#\">Contact</a>\n</nav>",
"previewBaseCSS": "body { font-family: system-ui; padding: 1rem; } nav { display: flex; gap: 1.5rem; }",
"sandboxCSS": "",
"codePrefix": "",
"initialCode": "",
"codeSuffix": "",
"previewContainer": "preview-area",
"solution": "a {\n color: coral;\n}",
"validations": [
{
"type": "regex",
"value": "a\\s*\\{",
"message": "Zacznij od <kbd>a {</kbd> aby wybrać linki"
},
{
"type": "property_value",
"value": { "property": "color", "expected": "coral" },
"message": "Sprawdź właściwość <kbd>color</kbd> — jaki kolor potrzebują linki?"
}
]
},
{
"id": "class-selectors",
"title": "Selektory klas",
"description": "Selektory typu stylizują <em>wszystkie</em> elementy danego typu. Ale co jeśli chcesz ostylować tylko niektóre z nich?<br><br><strong>Selektory klas</strong> celują w elementy z określonym atrybutem <kbd>class</kbd>. Zaczynają się od kropki:<br><br><pre>.badge {<br> background: coral;<br>}</pre><br>To stylizuje tylko elementy z <kbd>class=\"badge\"</kbd>.",
"task": "Ostyluj badge powiadomień. Napisz regułę z <kbd>.badge</kbd> jako selektorem i ustaw <kbd>background: tomato</kbd>.",
"previewHTML": "<header>\n <h1>Dashboard</h1>\n <span class=\"badge\">3</span>\n</header>\n<p>You have new notifications waiting.</p>",
"previewBaseCSS": "body { font-family: system-ui; padding: 1rem; } header { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1rem; } h1 { margin: 0; font-size: 1.5rem; } .badge { color: white; padding: 0.25rem 0.5rem; border-radius: 999px; font-size: 0.875rem; } p { color: #555; margin: 0; }",
"sandboxCSS": "",
"codePrefix": "",
"initialCode": "",
"codeSuffix": "",
"previewContainer": "preview-area",
"solution": ".badge {\n background: tomato;\n}",
"validations": [
{
"type": "regex",
"value": "\\.badge\\s*\\{",
"message": "Zacznij od <kbd>.badge {</kbd> (nie zapomnij o kropce!)"
},
{
"type": "property_value",
"value": { "property": "background", "expected": "tomato" },
"message": "Sprawdź właściwość <kbd>background</kbd> — jaki kolor potrzebuje badge?"
}
]
},
{
"id": "button-variants",
"title": "Warianty przycisków",
"description": "Elementy mogą mieć wiele klas. Gdy łączysz selektory klas bez spacji, celujesz w elementy które mają <em>wszystkie</em> te klasy:<br><br><pre>.btn.primary {<br> background: steelblue;<br>}</pre><br>To celuje w elementy z <kbd>class=\"btn primary\"</kbd>, nie tylko <kbd>.btn</kbd> lub tylko <kbd>.primary</kbd>.",
"task": "Ostyluj główny przycisk. Napisz regułę z <kbd>.btn.primary</kbd> jako selektorem i ustaw <kbd>background: steelblue</kbd>.",
"previewHTML": "<div class=\"actions\">\n <button class=\"btn\">Cancel</button>\n <button class=\"btn primary\">Save Changes</button>\n</div>",
"previewBaseCSS": "body { font-family: system-ui; padding: 1rem; } .actions { display: flex; gap: 0.75rem; } .btn { padding: 0.5rem 1rem; border: none; border-radius: 6px; font-size: 1rem; cursor: pointer; background: #e0e0e0; color: #333; }",
"sandboxCSS": "",
"codePrefix": "",
"initialCode": "",
"codeSuffix": "",
"previewContainer": "preview-area",
"solution": ".btn.primary {\n background: steelblue;\n}",
"validations": [
{
"type": "regex",
"value": "\\.btn\\.primary\\s*\\{",
"message": "Użyj <kbd>.btn.primary {</kbd> (bez spacji między klasami)"
},
{
"type": "property_value",
"value": { "property": "background", "expected": "steelblue" },
"message": "Sprawdź właściwość <kbd>background</kbd> — jaki kolor potrzebuje przycisk?"
}
]
},
{
"id": "specific-elements",
"title": "Celowanie w konkretne elementy",
"description": "Czasem chcesz, żeby klasa wyglądała inaczej na różnych elementach. Połącz selektor typu z selektorem klasy (bez spacji) aby być bardziej specyficznym:<br><br><pre>a.btn {<br> text-decoration: none;<br>}</pre><br>To stylizuje tylko elementy <kbd>&lt;a&gt;</kbd> z klasą <kbd>btn</kbd>, nie elementy <kbd>&lt;button&gt;</kbd> z tą klasą.",
"task": "Usuń podkreślenie z przycisków-linków. Napisz regułę z <kbd>a.btn</kbd> jako selektorem i ustaw <kbd>text-decoration: none</kbd>.",
"previewHTML": "<div class=\"actions\">\n <button class=\"btn\">Regular Button</button>\n <a href=\"#\" class=\"btn\">Link Button</a>\n</div>",
"previewBaseCSS": "body { font-family: system-ui; padding: 1rem; } .actions { display: flex; gap: 0.75rem; align-items: center; } .btn { padding: 0.5rem 1rem; border: none; border-radius: 6px; font-size: 1rem; cursor: pointer; background: steelblue; color: white; }",
"sandboxCSS": "",
"codePrefix": "",
"initialCode": "",
"codeSuffix": "",
"previewContainer": "preview-area",
"solution": "a.btn {\n text-decoration: none;\n}",
"validations": [
{
"type": "regex",
"value": "a\\.btn\\s*\\{",
"message": "Użyj <kbd>a.btn {</kbd> (typ + klasa, bez spacji)"
},
{
"type": "property_value",
"value": { "property": "text-decoration", "expected": "none" },
"message": "Która właściwość kontroluje podkreślenie linków?"
}
]
},
{
"id": "grouping-selectors",
"title": "Grupowanie selektorów",
"description": "Gdy wiele elementów potrzebuje tych samych stylów, wymień je oddzielone przecinkami. To utrzymuje CSS czystym i łatwym w utrzymaniu.<br><br><pre>h1, h2, h3 {<br> color: steelblue;<br>}</pre><br>To stosuje ten sam kolor do wszystkich trzech poziomów nagłówków w jednej regule.",
"task": "Ostyluj wszystkie nagłówki jednolicie. Dodaj <kbd>color: steelblue</kbd> do zgrupowanego selektora <kbd>h1, h2, h3</kbd>.",
"previewHTML": "<article><h1>Main Title</h1><p>Introduction paragraph with some text.</p><h2>Section Heading</h2><p>More content here.</p><h3>Subsection</h3><p>Final paragraph.</p></article>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } article { max-width: 500px; } p { color: #555; line-height: 1.6; }",
"sandboxCSS": "",
"codePrefix": "h1, h2, h3 {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"previewContainer": "preview-area",
"solution": "color: steelblue;",
"validations": [
{
"type": "property_value",
"value": { "property": "color", "expected": "steelblue" },
"message": "Która właściwość kontroluje kolor tekstu nagłówków?"
}
]
},
{
"id": "descendant-selectors",
"title": "Selektory potomków",
"description": "Celuj w elementy wewnątrz innych elementów używając spacji między selektorami. To jeden z najbardziej użytecznych wzorców w CSS.<br><br><pre>.nav a {<br> color: white;<br>}</pre><br>To stylizuje tylko linki wewnątrz <kbd>.nav</kbd>, pozostawiając inne linki bez zmian.",
"task": "Ostyluj linki nawigacji inaczej. Napisz regułę z <kbd>.nav a</kbd> jako selektorem i ustaw <kbd>color: white</kbd>.",
"previewHTML": "<nav class=\"nav\"><a href=\"#\">Home</a><a href=\"#\">About</a><a href=\"#\">Contact</a></nav><p>Read more in our <a href=\"#\">documentation</a>.</p>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; margin: 0; } .nav { background: steelblue; padding: 1rem; display: flex; gap: 1rem; border-radius: 8px; margin-bottom: 1rem; } .nav a { text-decoration: none; } p a { color: steelblue; }",
"sandboxCSS": "",
"codePrefix": "",
"initialCode": "",
"codeSuffix": "",
"previewContainer": "preview-area",
"solution": ".nav a {\n color: white;\n}",
"validations": [
{
"type": "regex",
"value": "\\.nav\\s+a\\s*\\{",
"message": "Użyj <kbd>.nav a {</kbd> (spacja między .nav a a)"
},
{
"type": "property_value",
"value": { "property": "color", "expected": "white" },
"message": "Sprawdź właściwość <kbd>color</kbd> — jaki kolor potrzebują linki nawigacji?"
}
]
},
{
"id": "nested-styling",
"title": "Zagnieżdżone style",
"description": "Selektory potomków pozwalają tworzyć style kontekstowe. Ten sam element może wyglądać inaczej w zależności od tego gdzie się znajduje.<br><br>Na przykład, akapity w <kbd>.card</kbd> mogą być mniejsze niż akapity w <kbd>article</kbd>.",
"task": "Zmniejsz akapity wewnątrz karty. Napisz regułę z <kbd>.card p</kbd> jako selektorem i ustaw <kbd>font-size: 0.9rem</kbd>.",
"previewHTML": "<article><h2>Article Title</h2><p>This is a regular article paragraph with normal-sized text for comfortable reading.</p><div class=\"card\"><strong>Quick Tip</strong><p>Card paragraphs should be slightly smaller to fit the compact design.</p></div><p>Back to regular article text here.</p></article>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } article { max-width: 500px; } h2 { color: steelblue; margin-top: 0; } p { line-height: 1.6; color: #444; } .card { background: #f0f4f8; padding: 1rem; border-radius: 8px; border-left: 4px solid steelblue; } .card strong { color: steelblue; display: block; margin-bottom: 0.5rem; }",
"sandboxCSS": "",
"codePrefix": "",
"initialCode": "",
"codeSuffix": "",
"previewContainer": "preview-area",
"solution": ".card p {\n font-size: 0.9rem;\n}",
"validations": [
{
"type": "regex",
"value": "\\.card\\s+p\\s*\\{",
"message": "Użyj <kbd>.card p {</kbd> (spacja między .card a p)"
},
{
"type": "property_value",
"value": { "property": "font-size", "expected": "0.9rem" },
"message": "Która właściwość kontroluje rozmiar tekstu?"
}
]
}
]
}