{ "$schema": "../../schemas/code-crispies-module-schema.json", "id": "flexbox", "title": "CSS Flexbox", "description": "Opanuj model elastycznego układu pudełkowego dla nowoczesnych responsywnych projektów", "difficulty": "intermediate", "lessons": [ { "id": "flexbox-1", "title": "Container", "description": "Przed flexboxem nawet proste układy wymagały floatów, hacków pozycjonowania lub układów tabelarycznych. Flexbox (Flexible Box Layout) zrewolucjonizował CSS, dostarczając jednowymiarowy system układu zaprojektowany specjalnie do dystrybucji przestrzeni i wyrównywania zawartości.

Jak to działa: Gdy ustawisz display: flex na elemencie, staje się on kontenerem flex. Jego bezpośrednie dzieci automatycznie stają się elementami flex, które płyną wzdłuż osi głównej (domyślnie poziomej). Ta jedna właściwość przekształca ułożone elementy blokowe w poziomy rząd.

Dwie osie:
Oś główna – Główny kierunek przepływu elementów (row = lewo→prawo)
Oś poprzeczna – Prostopadła do głównej (row = góra→dół)

.nav {\n  display: flex;\n}
", "task": "To menu nawigacyjne układa się pionowo. Dodaj display: flex, aby ułożyć linki poziomo.", "previewHTML": "", "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": "Ustaw display: flex" } ] }, { "id": "flexbox-2", "title": "Gap", "description": "Właściwość gap dodaje równomierne odstępy między elementami flex bez potrzeby używania marginesów. Tworzy przestrzeń tylko między elementami, nie na krawędziach.", "task": "Dodaj gap: 1rem, aby równomiernie rozmieścić linki nawigacyjne.", "previewHTML": "", "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": "Ustaw gap: 1rem" } ] }, { "id": "flexbox-3", "title": "Justify Content", "description": "justify-content rozmieszcza elementy wzdłuż osi głównej. Popularne wartości:
flex-start – pakuj elementy na początku
flex-end – pakuj na końcu
center – wyśrodkuj elementy
space-between – równa przestrzeń między elementami
space-around – równa przestrzeń wokół elementów", "task": "Przesuń przycisk \"Login\" na prawą stronę, ustawiając justify-content: space-between na nawigacji.", "previewHTML": "", "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": "Ustaw justify-content: space-between" } ] }, { "id": "flexbox-4", "title": "Align Items", "description": "align-items kontroluje wyrównanie na osi poprzecznej (pionowo gdy flex-direction to row). Wartości to:
stretch – rozciągnij do wypełnienia (domyślnie)
flex-start – wyrównaj do góry
flex-end – wyrównaj do dołu
center – wyśrodkuj pionowo", "task": "Logo i linki nawigacyjne mają różne wysokości. Wyśrodkuj je pionowo za pomocą align-items: center.", "previewHTML": "
ACME
", "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": "Ustaw align-items: center" } ] }, { "id": "flexbox-5", "title": "Flex Wrap", "description": "Domyślnie elementy flex ściskają się w jednej linii. flex-wrap: wrap pozwala elementom przenosić się na kolejne linie, gdy zabraknie miejsca.", "task": "Te karty wychodzą poza kontener. Dodaj flex-wrap: wrap, aby mogły przenosić się do nowych wierszy.", "previewHTML": "
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
", "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": "Ustaw flex-wrap: wrap" } ] }, { "id": "flexbox-6", "title": "Flex Grow", "description": "Właściwość flex na elementach kontroluje ich rozrastanie i kurczenie się. flex: 1 sprawia, że element rozrasta się, aby wypełnić dostępną przestrzeń. Wiele elementów z flex: 1 dzieli przestrzeń równomiernie.", "task": "Spraw, aby pole wyszukiwania rozszerzyło się i wypełniło dostępną przestrzeń, ustawiając flex: 1 na .search.", "previewHTML": "
", "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": "Ustaw flex: 1" } ] } ] }