{ "$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ą deklaracji - par właściwości i wartości. Każda deklaracja ma ten sam wzorzec:

property: value;

Właściwość to co chcesz zmienić (jak color lub background). Wartość to na co to ustawiasz. Dwukropek je rozdziela, a średnik kończy linię.

Wartości występują w różnych typach:
Słowa kluczowe: red, bold, center
Liczby z jednostkami: 16px, 2rem, 100%
Kolory: steelblue, #ff0000", "task": "Uzupełnij deklarację dodając color: coral; aby zmienić kolor tekstu.", "previewHTML": "

This text should turn coral.

", "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": "Dodaj color: coral;" } ] }, { "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:

.box {
background: gold;
color: navy;
padding: 1rem;
}

Kolejność zwykle nie ma znaczenia - CSS stosuje wszystkie. Przy konfliktach wygrywa ostatnia.", "task": "Dodaj dwie deklaracje: background: lavender; i padding: 1rem;", "previewHTML": "
A styled card with background and padding.
", "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": "Dodaj background: lavender;" }, { "type": "property_value", "value": { "property": "padding", "expected": "1rem" }, "message": "Dodaj padding: 1rem;" } ] }, { "id": "type-selectors", "title": "Selektory typu", "description": "Selektor mówi przeglądarce, które elementy stylizować. Najprostszym selektorem jest selektor typu — po prostu nazwa tagu HTML.

p {
color: steelblue;
}

Ta reguła celuje w każdy element <p> na stronie. Selektory typu świetnie nadają się do ustawiania podstawowych stylów.", "task": "Ostyluj wszystkie akapity. Napisz regułę z p jako selektorem i ustaw color: steelblue.", "previewHTML": "
\n

Fresh Roasted Coffee

\n

Our beans are sourced from small farms in Colombia and Ethiopia.

\n

Each batch is roasted weekly to ensure peak freshness.

\n
", "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 p { aby wybrać akapity" }, { "type": "property_value", "value": { "property": "color", "expected": "steelblue" }, "message": "Ustaw color: steelblue" } ] }, { "id": "styling-links", "title": "Stylizowanie linków", "description": "Selektory typu działają dla każdego elementu HTML. Selektor a celuje we wszystkie linki na stronie.

Linki domyślnie mają niebieski kolor i podkreślenie. Możesz zmienić oba z CSS — użyj color dla tekstu i text-decoration: none aby usunąć podkreślenie.", "task": "Ostyluj linki nawigacji. Napisz regułę z a jako selektorem i ustaw color: coral.", "previewHTML": "", "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 a { aby wybrać linki" }, { "type": "property_value", "value": { "property": "color", "expected": "coral" }, "message": "Ustaw color: coral" } ] }, { "id": "class-selectors", "title": "Selektory klas", "description": "Selektory typu stylizują wszystkie elementy danego typu. Ale co jeśli chcesz ostylować tylko niektóre z nich?

Selektory klas celują w elementy z określonym atrybutem class. Zaczynają się od kropki:

.badge {
background: coral;
}

To stylizuje tylko elementy z class=\"badge\".", "task": "Ostyluj badge powiadomień. Napisz regułę z .badge jako selektorem i ustaw background: tomato.", "previewHTML": "
\n

Dashboard

\n 3\n
\n

You have new notifications waiting.

", "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 .badge { (nie zapomnij o kropce!)" }, { "type": "property_value", "value": { "property": "background", "expected": "tomato" }, "message": "Ustaw background: tomato" } ] }, { "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ą wszystkie te klasy:

.btn.primary {
background: steelblue;
}

To celuje w elementy z class=\"btn primary\", nie tylko .btn lub tylko .primary.", "task": "Ostyluj główny przycisk. Napisz regułę z .btn.primary jako selektorem i ustaw background: steelblue.", "previewHTML": "
\n \n \n
", "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 .btn.primary { (bez spacji między klasami)" }, { "type": "property_value", "value": { "property": "background", "expected": "steelblue" }, "message": "Ustaw background: steelblue" } ] }, { "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:

a.btn {
text-decoration: none;
}

To stylizuje tylko elementy <a> z klasą btn, nie elementy <button> z tą klasą.", "task": "Usuń podkreślenie z przycisków-linków. Napisz regułę z a.btn jako selektorem i ustaw text-decoration: none.", "previewHTML": "
\n \n Link Button\n
", "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 a.btn { (typ + klasa, bez spacji)" }, { "type": "property_value", "value": { "property": "text-decoration", "expected": "none" }, "message": "Ustaw text-decoration: none" } ] }, { "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.

h1, h2, h3 {
color: steelblue;
}

To stosuje ten sam kolor do wszystkich trzech poziomów nagłówków w jednej regule.", "task": "Ostyluj wszystkie nagłówki jednolicie. Dodaj color: steelblue do zgrupowanego selektora h1, h2, h3.", "previewHTML": "

Main Title

Introduction paragraph with some text.

Section Heading

More content here.

Subsection

Final paragraph.

", "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": "Ustaw color: steelblue" } ] }, { "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.

.nav a {
color: white;
}

To stylizuje tylko linki wewnątrz .nav, pozostawiając inne linki bez zmian.", "task": "Ostyluj linki nawigacji inaczej. Napisz regułę z .nav a jako selektorem i ustaw color: white.", "previewHTML": "

Read more in our documentation.

", "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 .nav a { (spacja między .nav a a)" }, { "type": "property_value", "value": { "property": "color", "expected": "white" }, "message": "Ustaw color: white" } ] }, { "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.

Na przykład, akapity w .card mogą być mniejsze niż akapity w article.", "task": "Zmniejsz akapity wewnątrz karty. Napisz regułę z .card p jako selektorem i ustaw font-size: 0.9rem.", "previewHTML": "

Article Title

This is a regular article paragraph with normal-sized text for comfortable reading.

Quick Tip

Card paragraphs should be slightly smaller to fit the compact design.

Back to regular article text here.

", "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 .card p { (spacja między .card a p)" }, { "type": "property_value", "value": { "property": "font-size", "expected": "0.9rem" }, "message": "Ustaw font-size: 0.9rem" } ] } ] }