diff --git a/lessons/ar/flexbox.json b/lessons/ar/flexbox.json index 7b34c96..5338883 100644 --- a/lessons/ar/flexbox.json +++ b/lessons/ar/flexbox.json @@ -2,18 +2,18 @@ "$schema": "../../schemas/code-crispies-module-schema.json", "id": "flexbox", "title": "CSS Flexbox", - "description": "Master the flexible box layout model for modern responsive designs", + "description": "أتقن نموذج تخطيط الصندوق المرن للتصاميم المتجاوبة الحديثة", "difficulty": "intermediate", "lessons": [ { "id": "flexbox-1", "title": "Container", - "description": "Learn how to create a flex container and understand the main and cross axes.", - "task": "Add display: flex to .wrap to create a flexbox layout.", - "previewHTML": "
1
2
3
", - "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": "قبل flexbox، كانت حتى التخطيطات البسيطة تتطلب floats أو حيل التموضع أو تخطيطات الجداول. ثورة Flexbox (تخطيط الصندوق المرن) في CSS من خلال توفير نظام تخطيط أحادي البعد مصمم خصيصاً لتوزيع المساحة ومحاذاة المحتوى.

كيف يعمل: عندما تضبط display: flex على عنصر، يصبح حاوية flex. أبناؤه المباشرون يصبحون تلقائياً عناصر flex تتدفق على طول المحور الرئيسي (أفقياً بشكل افتراضي). هذه الخاصية الواحدة تحول العناصر الكتلية المتراصة إلى صف أفقي.

المحوران:
المحور الرئيسي – الاتجاه الأساسي لتدفق العناصر (row = يسار→يمين)
المحور المتقاطع – عمودي على الرئيسي (row = أعلى→أسفل)

.nav {\n  display: flex;\n}
", + "task": "قائمة التنقل هذه تتراص عمودياً. أضف display: flex لترتيب الروابط أفقياً.", + "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;", @@ -21,61 +21,41 @@ "validations": [ { "type": "property_value", - "value": { - "property": "display", - "expected": "flex" - }, - "message": "Set display: flex" + "value": { "property": "display", "expected": "flex" }, + "message": "اضبط display: flex" } ] }, { "id": "flexbox-2", - "title": "Direction & Wrap", - "description": "Control the direction and wrapping of flex items within a container.", - "task": "Add flex-direction: column and flex-wrap: wrap to .wrap.", - "previewHTML": "
1
2
3
4
5
", - "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": "خاصية gap تضيف تباعداً متسقاً بين عناصر flex بدون الحاجة إلى الهوامش. تُنشئ مساحة فقط بين العناصر، وليس على الحواف.", + "task": "أضف gap: 1rem لتوزيع روابط التنقل بالتساوي.", + "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": "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 flex-direction: column", - "options": { - "exact": true - } - }, - { - "type": "property_value", - "value": { - "property": "flex-wrap", - "expected": "wrap" - }, - "message": "Set flex-wrap: wrap", - "options": { - "exact": true - } + "value": { "property": "gap", "expected": "1rem" }, + "message": "اضبط gap: 1rem" } ] }, { "id": "flexbox-3", "title": "Justify Content", - "description": "Learn how to align flex items along the main axis of the flex container.", - "task": "Add justify-content: space-between to .wrap to distribute the boxes evenly.", - "previewHTML": "
1
2
3
", - "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": "justify-content يوزع العناصر على طول المحور الرئيسي. القيم الشائعة:
flex-start – تجميع في البداية
flex-end – تجميع في النهاية
center – توسيط العناصر
space-between – مسافة متساوية بين العناصر
space-around – مسافة متساوية حول العناصر", + "task": "ادفع زر \"Login\" إلى اليمين بضبط justify-content: space-between على التنقل.", + "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;", @@ -83,26 +63,20 @@ "validations": [ { "type": "property_value", - "value": { - "property": "justify-content", - "expected": "space-between" - }, - "message": "Set justify-content: space-between", - "options": { - "exact": true - } + "value": { "property": "justify-content", "expected": "space-between" }, + "message": "اضبط justify-content: space-between" } ] }, { "id": "flexbox-4", "title": "Align Items", - "description": "Control how flex items are aligned along the cross axis of the flex container.", - "task": "Add align-items: center to .wrap to vertically center the boxes.", - "previewHTML": "
1
2
3
", - "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": "align-items يتحكم في المحاذاة على المحور المتقاطع (عمودياً عندما يكون flex-direction هو row). القيم تشمل:
stretch – تمديد للملء (افتراضي)
flex-start – محاذاة للأعلى
flex-end – محاذاة للأسفل
center – توسيط عمودي", + "task": "الشعار وروابط التنقل لها ارتفاعات مختلفة. وسّطها عمودياً باستخدام 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;", @@ -110,62 +84,50 @@ "validations": [ { "type": "property_value", - "value": { - "property": "align-items", - "expected": "center" - }, - "message": "Set align-items: center", - "options": { - "exact": true - } + "value": { "property": "align-items", "expected": "center" }, + "message": "اضبط align-items: center" } ] }, { "id": "flexbox-5", - "title": "Flex Grow", - "description": "The flex property controls how much an item grows relative to others.", - "task": "Add flex: 2 to .box2 to make it grow twice as wide.", - "previewHTML": "
1
2
3
", - "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": "بشكل افتراضي، تنضغط عناصر flex في سطر واحد. flex-wrap: wrap يسمح للعناصر بالتدفق إلى أسطر متعددة عندما تنفد المساحة.", + "task": "هذه البطاقات تتجاوز الحاوية. أضف flex-wrap: wrap للسماح لها بالانتقال إلى صفوف جديدة.", + "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: 2;", + "solution": "flex-wrap: wrap;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "flex", - "expected": "2" - }, - "message": "Set flex: 2" + "value": { "property": "flex-wrap", "expected": "wrap" }, + "message": "اضبط flex-wrap: wrap" } ] }, { "id": "flexbox-6", - "title": "Align Self", - "description": "Use align-self to override alignment for a single flex item.", - "task": "Add align-self: flex-start to .middle to move it to the top.", - "previewHTML": "
1
2
3
", - "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": "خاصية flex على العناصر تتحكم في كيفية نموها وانكماشها. flex: 1 يجعل العنصر ينمو لملء المساحة المتاحة. عناصر متعددة مع flex: 1 تتشارك المساحة بالتساوي.", + "task": "اجعل حقل البحث يتوسع لملء المساحة المتاحة بضبط flex: 1 على .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": "align-self: flex-start;", + "solution": "flex: 1;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "align-self", - "expected": "flex-start" - }, - "message": "Set align-self: flex-start" + "value": { "property": "flex", "expected": "1" }, + "message": "اضبط flex: 1" } ] } diff --git a/lessons/de/flexbox.json b/lessons/de/flexbox.json index 54b3a07..a66f6b3 100644 --- a/lessons/de/flexbox.json +++ b/lessons/de/flexbox.json @@ -7,13 +7,13 @@ "lessons": [ { "id": "flexbox-1", - "title": "Flex Container", - "description": "Flexbox ist ein eindimensionales Layout-System. Mit display: flex wird ein Element zum Flex-Container. Alle direkten Kinder werden automatisch zu Flex-Items und richten sich horizontal (Hauptachse) aus. Die Querachse verläuft senkrecht dazu.", - "task": "Füge display: flex zu .wrap hinzu.", - "previewHTML": "
1
2
3
", - "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 ", + "title": "Container", + "description": "Vor Flexbox erforderten selbst einfache Layouts Floats, Positionierungs-Hacks oder tabellenbasierte Layouts. Flexbox (Flexible Box Layout) revolutionierte CSS, indem es ein eindimensionales Layout-System speziell für Platzverteilung und Inhaltsausrichtung bereitstellte.

So funktioniert es: Wenn du display: flex auf ein Element setzt, wird es zum Flex-Container. Seine direkten Kinder werden automatisch zu Flex-Items, die entlang einer Hauptachse fließen (standardmäßig horizontal). Diese eine Eigenschaft verwandelt gestapelte Block-Elemente in eine horizontale Reihe.

Die zwei Achsen:
Hauptachse – Die primäre Richtung, in der Items fließen (row = links→rechts)
Querachse – Senkrecht zur Hauptachse (row = oben→unten)

.nav {\n  display: flex;\n}
", + "task": "Dieses Navigationsmenü stapelt sich vertikal. Füge display: flex hinzu, um die Links horizontal anzuordnen.", + "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;", @@ -28,41 +28,34 @@ }, { "id": "flexbox-2", - "title": "Direction & Wrap", - "description": "flex-direction bestimmt die Hauptachse: row (horizontal, Standard) oder column (vertikal). Mit flex-wrap: wrap brechen Items in die nächste Zeile/Spalte um, wenn der Platz nicht reicht.", - "task": "Füge flex-direction: column und flex-wrap: wrap zu .wrap hinzu.", - "previewHTML": "
1
2
3
4
5
", - "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": "Die gap-Eigenschaft fügt konsistenten Abstand zwischen Flex-Items hinzu, ohne dass Margins nötig sind. Sie erzeugt nur Platz zwischen Items, nicht an den Rändern.", + "task": "Füge gap: 1rem hinzu, um die Navigationslinks gleichmäßig zu verteilen.", + "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": "flex-direction: column;\n flex-wrap: wrap;", + "solution": "gap: 1rem;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { "property": "flex-direction", "expected": "column" }, - "message": "Setze flex-direction: column", - "options": { "exact": true } - }, - { - "type": "property_value", - "value": { "property": "flex-wrap", "expected": "wrap" }, - "message": "Setze flex-wrap: wrap", - "options": { "exact": true } + "value": { "property": "gap", "expected": "1rem" }, + "message": "Setze gap: 1rem" } ] }, { "id": "flexbox-3", "title": "Justify Content", - "description": "justify-content verteilt Items entlang der Hauptachse. Werte: flex-start (Anfang), flex-end (Ende), center (Mitte), space-between (gleichmäßig mit Abstand), space-around (gleichmäßig mit Rand).", - "task": "Füge justify-content: space-between zu .wrap hinzu.", - "previewHTML": "
1
2
3
", - "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": "justify-content verteilt Items entlang der Hauptachse. Häufige Werte:
flex-start – Items am Anfang
flex-end – Items am Ende
center – Items zentrieren
space-between – Gleicher Abstand zwischen Items
space-around – Gleicher Abstand um Items", + "task": "Schiebe den \"Login\"-Button nach rechts, indem du justify-content: space-between auf die Navigation setzt.", + "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;", @@ -71,20 +64,19 @@ { "type": "property_value", "value": { "property": "justify-content", "expected": "space-between" }, - "message": "Setze justify-content: space-between", - "options": { "exact": true } + "message": "Setze justify-content: space-between" } ] }, { "id": "flexbox-4", "title": "Align Items", - "description": "align-items richtet Items entlang der Querachse aus (bei row: vertikal). Werte: stretch (Standard, füllt Höhe), flex-start (oben), flex-end (unten), center (Mitte), baseline (Textlinie).", - "task": "Füge align-items: center zu .wrap hinzu.", - "previewHTML": "
1
2
3
", - "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": "align-items steuert die Ausrichtung auf der Querachse (vertikal bei flex-direction: row). Werte sind:
stretch – Ausdehnen zum Füllen (Standard)
flex-start – Oben ausrichten
flex-end – Unten ausrichten
center – Vertikal zentrieren", + "task": "Das Logo und die Nav-Links haben unterschiedliche Höhen. Zentriere sie vertikal mit 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;", @@ -93,50 +85,49 @@ { "type": "property_value", "value": { "property": "align-items", "expected": "center" }, - "message": "Setze align-items: center", - "options": { "exact": true } + "message": "Setze align-items: center" } ] }, { "id": "flexbox-5", - "title": "Flex Grow", - "description": "Die flex-Eigenschaft ist eine Kurzform für flex-grow, flex-shrink und flex-basis. Ein höherer Wert bedeutet, dass das Element mehr vom verfügbaren Platz einnimmt. flex: 2 wächst doppelt so schnell wie flex: 1.", - "task": "Füge flex: 2 zu .box2 hinzu.", - "previewHTML": "
1
2
3
", - "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": "Standardmäßig quetschen sich Flex-Items in eine Zeile. flex-wrap: wrap erlaubt Items, auf mehrere Zeilen umzubrechen, wenn der Platz nicht reicht.", + "task": "Diese Karten laufen über den Container hinaus. Füge flex-wrap: wrap hinzu, damit sie in neue Zeilen umbrechen können.", + "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: 2;", + "solution": "flex-wrap: wrap;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { "property": "flex", "expected": "2" }, - "message": "Setze flex: 2" + "value": { "property": "flex-wrap", "expected": "wrap" }, + "message": "Setze flex-wrap: wrap" } ] }, { "id": "flexbox-6", - "title": "Align Self", - "description": "align-self überschreibt align-items für ein einzelnes Element. So kannst du ein Item individuell auf der Querachse positionieren, während alle anderen Items ihrer Standard-Ausrichtung folgen.", - "task": "Füge align-self: flex-start zu .middle hinzu.", - "previewHTML": "
1
2
3
", - "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": "Die flex-Eigenschaft auf Items steuert, wie sie wachsen und schrumpfen. flex: 1 lässt ein Item wachsen, um verfügbaren Platz zu füllen. Mehrere Items mit flex: 1 teilen sich den Platz gleichmäßig.", + "task": "Lass das Suchfeld den verfügbaren Platz ausfüllen, indem du flex: 1 auf .search setzt.", + "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": "align-self: flex-start;", + "solution": "flex: 1;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { "property": "align-self", "expected": "flex-start" }, - "message": "Setze align-self: flex-start" + "value": { "property": "flex", "expected": "1" }, + "message": "Setze flex: 1" } ] } diff --git a/lessons/es/flexbox.json b/lessons/es/flexbox.json index 7b34c96..5c2270d 100644 --- a/lessons/es/flexbox.json +++ b/lessons/es/flexbox.json @@ -2,18 +2,18 @@ "$schema": "../../schemas/code-crispies-module-schema.json", "id": "flexbox", "title": "CSS Flexbox", - "description": "Master the flexible box layout model for modern responsive designs", + "description": "Domina el modelo de caja flexible para diseños responsivos modernos", "difficulty": "intermediate", "lessons": [ { "id": "flexbox-1", "title": "Container", - "description": "Learn how to create a flex container and understand the main and cross axes.", - "task": "Add display: flex to .wrap to create a flexbox layout.", - "previewHTML": "
1
2
3
", - "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": "Antes de flexbox, incluso los diseños simples requerían floats, hacks de posicionamiento o diseños basados en tablas. Flexbox (Flexible Box Layout) revolucionó CSS al proporcionar un sistema de diseño unidimensional diseñado específicamente para distribuir espacio y alinear contenido.

Cómo funciona: Cuando estableces display: flex en un elemento, se convierte en un contenedor flex. Sus hijos directos automáticamente se convierten en elementos flex que fluyen a lo largo de un eje principal (horizontal por defecto). Esta única propiedad transforma elementos de bloque apilados en una fila horizontal.

Los dos ejes:
Eje principal – La dirección primaria del flujo de elementos (row = izquierda→derecha)
Eje transversal – Perpendicular al principal (row = arriba→abajo)

.nav {\n  display: flex;\n}
", + "task": "Este menú de navegación se apila verticalmente. Añade display: flex para organizar los enlaces horizontalmente.", + "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;", @@ -21,61 +21,41 @@ "validations": [ { "type": "property_value", - "value": { - "property": "display", - "expected": "flex" - }, - "message": "Set display: flex" + "value": { "property": "display", "expected": "flex" }, + "message": "Establece display: flex" } ] }, { "id": "flexbox-2", - "title": "Direction & Wrap", - "description": "Control the direction and wrapping of flex items within a container.", - "task": "Add flex-direction: column and flex-wrap: wrap to .wrap.", - "previewHTML": "
1
2
3
4
5
", - "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": "La propiedad gap añade espaciado consistente entre elementos flex sin necesidad de márgenes. Solo crea espacio entre elementos, no en los bordes.", + "task": "Añade gap: 1rem para espaciar uniformemente los enlaces de navegación.", + "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": "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 flex-direction: column", - "options": { - "exact": true - } - }, - { - "type": "property_value", - "value": { - "property": "flex-wrap", - "expected": "wrap" - }, - "message": "Set flex-wrap: wrap", - "options": { - "exact": true - } + "value": { "property": "gap", "expected": "1rem" }, + "message": "Establece gap: 1rem" } ] }, { "id": "flexbox-3", "title": "Justify Content", - "description": "Learn how to align flex items along the main axis of the flex container.", - "task": "Add justify-content: space-between to .wrap to distribute the boxes evenly.", - "previewHTML": "
1
2
3
", - "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": "justify-content distribuye elementos a lo largo del eje principal. Valores comunes:
flex-start – agrupar al inicio
flex-end – agrupar al final
center – centrar elementos
space-between – espacio igual entre elementos
space-around – espacio igual alrededor de elementos", + "task": "Empuja el botón \"Login\" hacia la derecha estableciendo justify-content: space-between en la navegación.", + "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;", @@ -83,26 +63,20 @@ "validations": [ { "type": "property_value", - "value": { - "property": "justify-content", - "expected": "space-between" - }, - "message": "Set justify-content: space-between", - "options": { - "exact": true - } + "value": { "property": "justify-content", "expected": "space-between" }, + "message": "Establece justify-content: space-between" } ] }, { "id": "flexbox-4", "title": "Align Items", - "description": "Control how flex items are aligned along the cross axis of the flex container.", - "task": "Add align-items: center to .wrap to vertically center the boxes.", - "previewHTML": "
1
2
3
", - "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": "align-items controla la alineación en el eje transversal (vertical cuando flex-direction es row). Los valores incluyen:
stretch – estirar para llenar (por defecto)
flex-start – alinear arriba
flex-end – alinear abajo
center – centrar verticalmente", + "task": "El logo y los enlaces de navegación tienen diferentes alturas. Céntralos verticalmente con 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;", @@ -110,62 +84,50 @@ "validations": [ { "type": "property_value", - "value": { - "property": "align-items", - "expected": "center" - }, - "message": "Set align-items: center", - "options": { - "exact": true - } + "value": { "property": "align-items", "expected": "center" }, + "message": "Establece align-items: center" } ] }, { "id": "flexbox-5", - "title": "Flex Grow", - "description": "The flex property controls how much an item grows relative to others.", - "task": "Add flex: 2 to .box2 to make it grow twice as wide.", - "previewHTML": "
1
2
3
", - "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": "Por defecto, los elementos flex se comprimen en una línea. flex-wrap: wrap permite que los elementos fluyan a múltiples líneas cuando se quedan sin espacio.", + "task": "Estas tarjetas desbordan el contenedor. Añade flex-wrap: wrap para permitir que pasen a nuevas filas.", + "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: 2;", + "solution": "flex-wrap: wrap;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "flex", - "expected": "2" - }, - "message": "Set flex: 2" + "value": { "property": "flex-wrap", "expected": "wrap" }, + "message": "Establece flex-wrap: wrap" } ] }, { "id": "flexbox-6", - "title": "Align Self", - "description": "Use align-self to override alignment for a single flex item.", - "task": "Add align-self: flex-start to .middle to move it to the top.", - "previewHTML": "
1
2
3
", - "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": "La propiedad flex en los elementos controla cómo crecen y se encogen. flex: 1 hace que un elemento crezca para llenar el espacio disponible. Múltiples elementos con flex: 1 comparten el espacio equitativamente.", + "task": "Haz que el campo de búsqueda se expanda para llenar el espacio disponible estableciendo flex: 1 en .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": "align-self: flex-start;", + "solution": "flex: 1;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "align-self", - "expected": "flex-start" - }, - "message": "Set align-self: flex-start" + "value": { "property": "flex", "expected": "1" }, + "message": "Establece flex: 1" } ] } diff --git a/lessons/pl/flexbox.json b/lessons/pl/flexbox.json index 7b34c96..5da2f19 100644 --- a/lessons/pl/flexbox.json +++ b/lessons/pl/flexbox.json @@ -2,18 +2,18 @@ "$schema": "../../schemas/code-crispies-module-schema.json", "id": "flexbox", "title": "CSS Flexbox", - "description": "Master the flexible box layout model for modern responsive designs", + "description": "Opanuj model elastycznego układu pudełkowego dla nowoczesnych responsywnych projektów", "difficulty": "intermediate", "lessons": [ { "id": "flexbox-1", "title": "Container", - "description": "Learn how to create a flex container and understand the main and cross axes.", - "task": "Add display: flex to .wrap to create a flexbox layout.", - "previewHTML": "
1
2
3
", - "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": "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;", @@ -21,61 +21,41 @@ "validations": [ { "type": "property_value", - "value": { - "property": "display", - "expected": "flex" - }, - "message": "Set display: flex" + "value": { "property": "display", "expected": "flex" }, + "message": "Ustaw display: flex" } ] }, { "id": "flexbox-2", - "title": "Direction & Wrap", - "description": "Control the direction and wrapping of flex items within a container.", - "task": "Add flex-direction: column and flex-wrap: wrap to .wrap.", - "previewHTML": "
1
2
3
4
5
", - "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": "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": "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 flex-direction: column", - "options": { - "exact": true - } - }, - { - "type": "property_value", - "value": { - "property": "flex-wrap", - "expected": "wrap" - }, - "message": "Set flex-wrap: wrap", - "options": { - "exact": true - } + "value": { "property": "gap", "expected": "1rem" }, + "message": "Ustaw gap: 1rem" } ] }, { "id": "flexbox-3", "title": "Justify Content", - "description": "Learn how to align flex items along the main axis of the flex container.", - "task": "Add justify-content: space-between to .wrap to distribute the boxes evenly.", - "previewHTML": "
1
2
3
", - "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": "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;", @@ -83,26 +63,20 @@ "validations": [ { "type": "property_value", - "value": { - "property": "justify-content", - "expected": "space-between" - }, - "message": "Set justify-content: space-between", - "options": { - "exact": true - } + "value": { "property": "justify-content", "expected": "space-between" }, + "message": "Ustaw justify-content: space-between" } ] }, { "id": "flexbox-4", "title": "Align Items", - "description": "Control how flex items are aligned along the cross axis of the flex container.", - "task": "Add align-items: center to .wrap to vertically center the boxes.", - "previewHTML": "
1
2
3
", - "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": "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;", @@ -110,62 +84,50 @@ "validations": [ { "type": "property_value", - "value": { - "property": "align-items", - "expected": "center" - }, - "message": "Set align-items: center", - "options": { - "exact": true - } + "value": { "property": "align-items", "expected": "center" }, + "message": "Ustaw align-items: center" } ] }, { "id": "flexbox-5", - "title": "Flex Grow", - "description": "The flex property controls how much an item grows relative to others.", - "task": "Add flex: 2 to .box2 to make it grow twice as wide.", - "previewHTML": "
1
2
3
", - "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": "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: 2;", + "solution": "flex-wrap: wrap;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "flex", - "expected": "2" - }, - "message": "Set flex: 2" + "value": { "property": "flex-wrap", "expected": "wrap" }, + "message": "Ustaw flex-wrap: wrap" } ] }, { "id": "flexbox-6", - "title": "Align Self", - "description": "Use align-self to override alignment for a single flex item.", - "task": "Add align-self: flex-start to .middle to move it to the top.", - "previewHTML": "
1
2
3
", - "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": "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": "align-self: flex-start;", + "solution": "flex: 1;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "align-self", - "expected": "flex-start" - }, - "message": "Set align-self: flex-start" + "value": { "property": "flex", "expected": "1" }, + "message": "Ustaw flex: 1" } ] } diff --git a/lessons/uk/flexbox.json b/lessons/uk/flexbox.json index 7b34c96..ce48da9 100644 --- a/lessons/uk/flexbox.json +++ b/lessons/uk/flexbox.json @@ -2,18 +2,18 @@ "$schema": "../../schemas/code-crispies-module-schema.json", "id": "flexbox", "title": "CSS Flexbox", - "description": "Master the flexible box layout model for modern responsive designs", + "description": "Опануйте модель гнучкого блочного макету для сучасних адаптивних дизайнів", "difficulty": "intermediate", "lessons": [ { "id": "flexbox-1", "title": "Container", - "description": "Learn how to create a flex container and understand the main and cross axes.", - "task": "Add display: flex to .wrap to create a flexbox layout.", - "previewHTML": "
1
2
3
", - "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": "До flexbox навіть прості макети вимагали floats, хаків позиціонування або табличних макетів. Flexbox (Flexible Box Layout) революціонізував CSS, надавши одновимірну систему макетування, спеціально розроблену для розподілу простору та вирівнювання вмісту.

Як це працює: Коли ви встановлюєте display: flex на елемент, він стає flex-контейнером. Його прямі нащадки автоматично стають flex-елементами, що розташовуються вздовж головної осі (горизонтально за замовчуванням). Ця одна властивість перетворює вкладені блокові елементи в горизонтальний ряд.

Дві осі:
Головна вісь – Основний напрямок потоку елементів (row = зліва→направо)
Поперечна вісь – Перпендикулярна до головної (row = зверху→вниз)

.nav {\n  display: flex;\n}
", + "task": "Це навігаційне меню розташовується вертикально. Додайте display: flex, щоб розташувати посилання горизонтально.", + "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;", @@ -21,61 +21,41 @@ "validations": [ { "type": "property_value", - "value": { - "property": "display", - "expected": "flex" - }, - "message": "Set display: flex" + "value": { "property": "display", "expected": "flex" }, + "message": "Встановіть display: flex" } ] }, { "id": "flexbox-2", - "title": "Direction & Wrap", - "description": "Control the direction and wrapping of flex items within a container.", - "task": "Add flex-direction: column and flex-wrap: wrap to .wrap.", - "previewHTML": "
1
2
3
4
5
", - "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": "Властивість gap додає послідовний відступ між flex-елементами без потреби у відступах (margins). Вона створює простір лише між елементами, а не по краях.", + "task": "Додайте gap: 1rem, щоб рівномірно розташувати навігаційні посилання.", + "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": "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 flex-direction: column", - "options": { - "exact": true - } - }, - { - "type": "property_value", - "value": { - "property": "flex-wrap", - "expected": "wrap" - }, - "message": "Set flex-wrap: wrap", - "options": { - "exact": true - } + "value": { "property": "gap", "expected": "1rem" }, + "message": "Встановіть gap: 1rem" } ] }, { "id": "flexbox-3", "title": "Justify Content", - "description": "Learn how to align flex items along the main axis of the flex container.", - "task": "Add justify-content: space-between to .wrap to distribute the boxes evenly.", - "previewHTML": "
1
2
3
", - "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": "justify-content розподіляє елементи вздовж головної осі. Поширені значення:
flex-start – групувати на початку
flex-end – групувати в кінці
center – центрувати елементи
space-between – рівний простір між елементами
space-around – рівний простір навколо елементів", + "task": "Перемістіть кнопку \"Login\" праворуч, встановивши justify-content: space-between на навігації.", + "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;", @@ -83,26 +63,20 @@ "validations": [ { "type": "property_value", - "value": { - "property": "justify-content", - "expected": "space-between" - }, - "message": "Set justify-content: space-between", - "options": { - "exact": true - } + "value": { "property": "justify-content", "expected": "space-between" }, + "message": "Встановіть justify-content: space-between" } ] }, { "id": "flexbox-4", "title": "Align Items", - "description": "Control how flex items are aligned along the cross axis of the flex container.", - "task": "Add align-items: center to .wrap to vertically center the boxes.", - "previewHTML": "
1
2
3
", - "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": "align-items керує вирівнюванням по поперечній осі (вертикально, коли flex-direction це row). Значення включають:
stretch – розтягнути для заповнення (за замовчуванням)
flex-start – вирівняти вгору
flex-end – вирівняти вниз
center – центрувати вертикально", + "task": "Логотип та навігаційні посилання мають різну висоту. Відцентруйте їх вертикально за допомогою 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;", @@ -110,62 +84,50 @@ "validations": [ { "type": "property_value", - "value": { - "property": "align-items", - "expected": "center" - }, - "message": "Set align-items: center", - "options": { - "exact": true - } + "value": { "property": "align-items", "expected": "center" }, + "message": "Встановіть align-items: center" } ] }, { "id": "flexbox-5", - "title": "Flex Grow", - "description": "The flex property controls how much an item grows relative to others.", - "task": "Add flex: 2 to .box2 to make it grow twice as wide.", - "previewHTML": "
1
2
3
", - "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": "За замовчуванням flex-елементи стискаються в один рядок. flex-wrap: wrap дозволяє елементам переходити на кілька рядків, коли місця недостатньо.", + "task": "Ці картки виходять за межі контейнера. Додайте flex-wrap: wrap, щоб дозволити їм переходити на нові рядки.", + "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: 2;", + "solution": "flex-wrap: wrap;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "flex", - "expected": "2" - }, - "message": "Set flex: 2" + "value": { "property": "flex-wrap", "expected": "wrap" }, + "message": "Встановіть flex-wrap: wrap" } ] }, { "id": "flexbox-6", - "title": "Align Self", - "description": "Use align-self to override alignment for a single flex item.", - "task": "Add align-self: flex-start to .middle to move it to the top.", - "previewHTML": "
1
2
3
", - "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": "Властивість flex на елементах керує тим, як вони ростуть і зменшуються. flex: 1 змушує елемент рости, щоб заповнити доступний простір. Кілька елементів з flex: 1 ділять простір порівну.", + "task": "Зробіть так, щоб поле пошуку розширилось і заповнило доступний простір, встановивши flex: 1 на .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": "align-self: flex-start;", + "solution": "flex: 1;", "previewContainer": "preview-area", "validations": [ { "type": "property_value", - "value": { - "property": "align-self", - "expected": "flex-start" - }, - "message": "Set align-self: flex-start" + "value": { "property": "flex", "expected": "1" }, + "message": "Встановіть flex: 1" } ] }