{ "$schema": "../schemas/code-crispies-module-schema.json", "id": "html-progress-meter", "title": "HTML Progress & Meter", "description": "Display completion status and scalar measurements natively", "mode": "html", "difficulty": "beginner", "lessons": [ { "id": "progress-basic", "title": "Progress Bars", "description": "The <progress> element shows task completion. Use value for current progress and max for the total.

Note: This is not a self-closing tag! Write <progress>...</progress> with fallback text inside for older browsers.", "task": "Create a progress bar showing 70% completion:
1. Add a <label> saying Download:
2. Add a <progress> with value=\"70\" and max=\"100\"", "previewHTML": "", "previewBaseCSS": "body { font-family: system-ui; padding: 20px; } label { display: block; margin-bottom: 8px; font-weight: 500; } progress { width: 100%; height: 20px; border-radius: 10px; } progress::-webkit-progress-bar { background: #e0e0e0; border-radius: 10px; } progress::-webkit-progress-value { background: linear-gradient(90deg, #4caf50, #8bc34a); border-radius: 10px; } progress::-moz-progress-bar { background: linear-gradient(90deg, #4caf50, #8bc34a); border-radius: 10px; }", "sandboxCSS": "", "initialCode": "", "solution": "\n70%", "previewContainer": "preview-area", "validations": [ { "type": "element_exists", "value": "progress", "message": "Add a <progress> element" }, { "type": "attribute_value", "value": { "selector": "progress", "attr": "value", "value": "70" }, "message": "Set value=\"70\" on the progress element" }, { "type": "attribute_value", "value": { "selector": "progress", "attr": "max", "value": "100" }, "message": "Set max=\"100\" on the progress element" }, { "type": "element_exists", "value": "label", "message": "Add a <label> for the progress bar" } ] }, { "id": "progress-indeterminate", "title": "Indeterminate Progress", "description": "When progress is unknown (like loading), omit the value attribute. This creates an animated indeterminate state.

Useful for network requests or processes with unknown duration.", "task": "Create a loading indicator:
1. Add a <p> saying Loading...
2. Add a <progress> without a value attribute", "previewHTML": "", "previewBaseCSS": "body { font-family: system-ui; padding: 20px; } p { margin-bottom: 10px; color: #666; } progress { width: 100%; height: 8px; border-radius: 4px; } progress::-webkit-progress-bar { background: #e0e0e0; border-radius: 4px; }", "sandboxCSS": "", "initialCode": "", "solution": "

Loading...

\n", "previewContainer": "preview-area", "validations": [ { "type": "element_exists", "value": "progress", "message": "Add a <progress> element" }, { "type": "element_exists", "value": "p", "message": "Add a <p> with loading text" } ] }, { "id": "meter-gauge", "title": "Meter Gauges", "description": "The <meter> element displays a scalar value within a range. Use it for measurements like disk space, battery, or ratings.

Set low, high, and optimum to define good/bad ranges - the browser colors it accordingly!", "task": "Create a battery level meter:
1. Add a <label> saying Battery:
2. Add a <meter> with:
- value=\"0.8\"
- min=\"0\" and max=\"1\"
- low=\"0.2\" and high=\"0.8\"
- optimum=\"1\"", "previewHTML": "", "previewBaseCSS": "body { font-family: system-ui; padding: 20px; } label { display: block; margin-bottom: 8px; font-weight: 500; } meter { width: 100%; height: 25px; }", "sandboxCSS": "", "initialCode": "", "solution": "\n80%", "previewContainer": "preview-area", "validations": [ { "type": "element_exists", "value": "meter", "message": "Add a <meter> element" }, { "type": "attribute_value", "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", "message": "Add a <label> for the meter" } ] } ] }