diff --git a/lessons/00-basic-selectors.json b/lessons/00-basic-selectors.json index 1b843e0..915798c 100644 --- a/lessons/00-basic-selectors.json +++ b/lessons/00-basic-selectors.json @@ -186,7 +186,7 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", - "solution": ".card.featured { border-color: gold; background-color: lemonchiffon }", + "solution": ".card.featured { border-color: gold; background-color: lemonchiffon; }", "validations": [ { "type": "regex", @@ -394,7 +394,7 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", - "solution": "p.note,\nli.important,\n#summary {\n background-color: lightyellow;\n border-left: 3px solid gold;\n padding-left: 10px\n}", + "solution": "p.note,\nli.important,\n#summary {\n background-color: lightyellow;\n border-left: 3px solid gold;\n padding-left: 10px;\n}", "validations": [ { "type": "contains", @@ -542,7 +542,7 @@ { "type": "contains", "value": "green", - "message": "" + "message": "Set the color to green" } ] } diff --git a/lessons/05-units-variables.json b/lessons/05-units-variables.json index caf64a5..2ffb2da 100644 --- a/lessons/05-units-variables.json +++ b/lessons/05-units-variables.json @@ -8,15 +8,15 @@ { "id": "units-1", "title": "Absolute vs. Relative Units", - "description": "Learn the difference between px, rem, em, %, and vw/vh for flexible, responsive layouts.", - "task": "Set the width of .box to 80% and max-width to 37.5rem.", + "description": "Learn the difference between px, rem, em, %, and vw/vh for flexible, responsive layouts.

width: 80%;      /* relative to parent */\nmax-width: 40rem; /* relative to root font */\npadding: 16px;   /* fixed pixels */
", + "task": "Set the width of .box to 80% and max-width to 40rem.", "previewHTML": "
Resize me!
", "previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .box { background: #f5f5f5; padding: 1rem; }", "sandboxCSS": "", "codePrefix": "/* Set flexible sizing */\n.box {", "initialCode": "", "codeSuffix": "}", - "solution": " width: 80%;\n max-width: 37.5rem;", + "solution": " width: 80%;\n max-width: 40rem;", "previewContainer": "preview-area", "validations": [ { "type": "contains", "value": "width", "message": "Use width property", "options": { "caseSensitive": false } }, @@ -24,23 +24,23 @@ { "type": "contains", "value": "max-width", "message": "Use max-width property", "options": { "caseSensitive": false } }, { "type": "property_value", - "value": { "property": "max-width", "expected": "37.5rem" }, - "message": "Set max-width to 37.5rem" + "value": { "property": "max-width", "expected": "40rem" }, + "message": "Set max-width to 40rem" } ] }, { "id": "units-2", "title": "CSS Custom Properties", - "description": "Define and reuse variables (--custom properties) to centralize your theme values.

:root {\n  --main-color: #6200ee;\n}\n.element {\n  color: var(--main-color);\n}
", - "task": "Create a --main-color variable in :root with #6200ee and apply it as the border color on .themed.", + "description": "Define and reuse variables (--custom properties) to centralize your theme values.

:root {\n  --main-color: mediumpurple;\n}\n.themed {\n  border-color: var(--main-color);\n}
", + "task": "Create a --main-color variable in :root with mediumpurple and apply it as the border color on .themed.", "previewHTML": "
Variable Box
", "previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .themed { padding: 1rem; border: 0.125rem solid #ddd; }", "sandboxCSS": "", "codePrefix": "/* Define and use a CSS variable */\n:root {", "initialCode": "", "codeSuffix": "}\n.themed { }", - "solution": " --main-color: #6200ee;\n}\n.themed {\n border-color: var(--main-color);", + "solution": " --main-color: mediumpurple;\n}\n.themed {\n border-color: var(--main-color);", "previewContainer": "preview-area", "validations": [ { @@ -66,7 +66,7 @@ { "id": "units-3", "title": "Unit Calculations (calc)", - "description": "Use the calc() function to combine different units in one expression.

.element {\n  width: calc(100% - 2rem);\n  height: calc(50vh + 1rem);\n}
", + "description": "Use the calc() function to combine different units in one expression.

width: calc(100% - 2rem);\nmin-height: calc(10vh + 1rem);
", "task": "Set the width of .sized to calc(100% - 2rem) and min-height to calc(10vh + 1rem).", "previewHTML": "
Calc Demo
", "previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .sized { background: #e8f5e9; padding: 1rem; }", @@ -95,7 +95,7 @@ { "id": "units-4", "title": "Viewport & Responsive Units", - "description": "Control layouts relative to viewport size with vw, vh, and vmin/vmax units.", + "description": "Control layouts relative to viewport size with vw, vh, and vmin/vmax units.

width: 50vw;   /* 50% of viewport width */\nheight: 20vh;  /* 20% of viewport height */
", "task": "Give .view a width of 50vw and height of 20vh.", "previewHTML": "
Viewport Box
", "previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .view { background: #ffe0b2; }", diff --git a/lessons/08-responsive.json b/lessons/08-responsive.json index 43de4e5..cd1be02 100644 --- a/lessons/08-responsive.json +++ b/lessons/08-responsive.json @@ -8,7 +8,7 @@ { "id": "responsive-1", "title": "Media Queries", - "description": "Understand the syntax and use cases for CSS media queries to apply styles conditionally based on viewport characteristics.

@media (max-width: 600px) {\n  .element {\n    background: lightcoral;\n  }\n}
", + "description": "Understand the syntax and use cases for CSS media queries to apply styles conditionally based on viewport characteristics.

@media (max-width: 600px) {\n  .panel {\n    background: lightcoral;\n  }\n}
", "task": "Write a media query with @media (max-width: 600px) that changes .panel background to lightcoral.", "previewHTML": "
Resize the window
", "previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; } .panel { padding: 1rem; background: lightblue; }", @@ -58,7 +58,7 @@ }, { "id": "responsive-3", - "title": "Flex Grids", + "title": "Responsive Grid", "description": "Combine CSS Grid with auto-fit or auto-fill for responsive column layouts.", "task": "Add display: grid, grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)), and gap: 1rem to .cards.", "previewHTML": "
1
2
3
4
", diff --git a/lessons/24-html-progress-meter.json b/lessons/24-html-progress-meter.json index 1bf278f..d8c2917 100644 --- a/lessons/24-html-progress-meter.json +++ b/lessons/24-html-progress-meter.json @@ -86,11 +86,31 @@ "value": { "selector": "meter", "attr": "value", "value": "0.8" }, "message": "Set value=\"0.8\" on the meter" }, + { + "type": "attribute_value", + "value": { "selector": "meter", "attr": "min", "value": "0" }, + "message": "Set min=\"0\" on the meter" + }, + { + "type": "attribute_value", + "value": { "selector": "meter", "attr": "max", "value": "1" }, + "message": "Set max=\"1\" on the meter" + }, { "type": "attribute_value", "value": { "selector": "meter", "attr": "low", "value": "0.2" }, "message": "Set low=\"0.2\" to define the low threshold" }, + { + "type": "attribute_value", + "value": { "selector": "meter", "attr": "high", "value": "0.8" }, + "message": "Set high=\"0.8\" to define the high threshold" + }, + { + "type": "attribute_value", + "value": { "selector": "meter", "attr": "optimum", "value": "1" }, + "message": "Set optimum=\"1\" to indicate the optimal value" + }, { "type": "element_exists", "value": "label", diff --git a/lessons/32-html-svg.json b/lessons/32-html-svg.json index 2a96917..37bd7a6 100644 --- a/lessons/32-html-svg.json +++ b/lessons/32-html-svg.json @@ -15,7 +15,7 @@ "previewBaseCSS": "body { font-family: system-ui; padding: 20px; background: #f5f5f5; display: flex; justify-content: center; } svg { background: white; border-radius: 10px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }", "sandboxCSS": "", "initialCode": "", - "solution": "\n \n", + "solution": "\n \n", "previewContainer": "preview-area", "validations": [ { @@ -28,6 +28,16 @@ "value": "circle", "message": "Add a <circle> element inside the SVG" }, + { + "type": "attribute_value", + "value": { "selector": "svg", "attr": "width", "value": "200" }, + "message": "Set width=\"200\" on the SVG" + }, + { + "type": "attribute_value", + "value": { "selector": "svg", "attr": "height", "value": "200" }, + "message": "Set height=\"200\" on the SVG" + }, { "type": "attribute_value", "value": { "selector": "circle", "attr": "cx", "value": "100" }, @@ -37,6 +47,11 @@ "type": "attribute_value", "value": { "selector": "circle", "attr": "cy", "value": "100" }, "message": "Set cy=\"100\" for the circle's vertical center" + }, + { + "type": "attribute_value", + "value": { "selector": "circle", "attr": "r", "value": "50" }, + "message": "Set r=\"50\" for the circle's radius" } ] }, @@ -49,7 +64,7 @@ "previewBaseCSS": "body { font-family: system-ui; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 200px; display: flex; justify-content: center; align-items: center; } svg { background: white; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); }", "sandboxCSS": "", "initialCode": "", - "solution": "\n \n \n", + "solution": "\n \n \n", "previewContainer": "preview-area", "validations": [ { @@ -66,6 +81,61 @@ "type": "element_exists", "value": "line", "message": "Add a <line> element" + }, + { + "type": "attribute_value", + "value": { "selector": "svg", "attr": "width", "value": "200" }, + "message": "Set width=\"200\" on the SVG" + }, + { + "type": "attribute_value", + "value": { "selector": "svg", "attr": "height", "value": "150" }, + "message": "Set height=\"150\" on the SVG" + }, + { + "type": "attribute_value", + "value": { "selector": "rect", "attr": "x", "value": "20" }, + "message": "Set x=\"20\" on the rect" + }, + { + "type": "attribute_value", + "value": { "selector": "rect", "attr": "y", "value": "20" }, + "message": "Set y=\"20\" on the rect" + }, + { + "type": "attribute_value", + "value": { "selector": "rect", "attr": "width", "value": "80" }, + "message": "Set width=\"80\" on the rect" + }, + { + "type": "attribute_value", + "value": { "selector": "rect", "attr": "height", "value": "60" }, + "message": "Set height=\"60\" on the rect" + }, + { + "type": "attribute_value", + "value": { "selector": "line", "attr": "x1", "value": "120" }, + "message": "Set x1=\"120\" on the line" + }, + { + "type": "attribute_value", + "value": { "selector": "line", "attr": "y1", "value": "30" }, + "message": "Set y1=\"30\" on the line" + }, + { + "type": "attribute_value", + "value": { "selector": "line", "attr": "x2", "value": "180" }, + "message": "Set x2=\"180\" on the line" + }, + { + "type": "attribute_value", + "value": { "selector": "line", "attr": "y2", "value": "90" }, + "message": "Set y2=\"90\" on the line" + }, + { + "type": "contains", + "value": "stroke", + "message": "Add a stroke color to the line" } ] }, @@ -78,7 +148,7 @@ "previewBaseCSS": "body { font-family: system-ui; padding: 20px; background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); min-height: 250px; display: flex; justify-content: center; align-items: center; } svg { background: white; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.15); }", "sandboxCSS": "", "initialCode": "", - "solution": "\n \n \n \n \n", + "solution": "\n \n \n \n \n", "previewContainer": "preview-area", "validations": [ {