Files
code-crispies/lessons/30-html-tables.json
Michael Czechowski 9cf313001b feat: add new lesson modules and reach 101 total lessons
New CSS Modules:
- Gradients (3 lessons): linear-gradient, radial-gradient, direction
- Filters (4 lessons): blur, grayscale, brightness, drop-shadow
- Positioning (4 lessons): relative, absolute, offset properties
- Pseudo-elements (4 lessons): ::before, ::after, content, decorative

New HTML Module:
- Semantic HTML (3 lessons): article, section, aside

Expanded Existing Modules:
- Typography: +2 lessons (text-decoration, text-shadow)
- Tables: +2 lessons (thead/tbody/tfoot, colspan)

Total lessons: 101 (up from ~66)
- Enables full milestone system (1, 5, 10, 20, 30, 50, 75, 100)
- All modules added to all 6 language stores with EN fallback
2026-01-16 14:17:13 +01:00

93 lines
5.7 KiB
JSON

{
"$schema": "../schemas/code-crispies-module-schema.json",
"id": "html-tables",
"title": "HTML Tables",
"description": "Create structured data tables with semantic markup",
"mode": "html",
"difficulty": "beginner",
"lessons": [
{
"id": "table-basic",
"title": "Data Tables",
"description": "Tables display structured data in rows and columns. Use <kbd>&lt;table&gt;</kbd> as the container, <kbd>&lt;tr&gt;</kbd> for rows, <kbd>&lt;th&gt;</kbd> for header cells, and <kbd>&lt;td&gt;</kbd> for data cells.<br><br>Add <kbd>&lt;caption&gt;</kbd> for an accessible title that describes the table's content.",
"task": "Create a pricing table:<br>1. A <kbd>&lt;caption&gt;</kbd> saying <code>Pricing</code><br>2. A header row with <code>Plan</code> and <code>Price</code><br>3. Two data rows for Basic ($9) and Pro ($29)",
"previewHTML": "",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; background: #f5f5f5; } table { border-collapse: collapse; width: 100%; max-width: 350px; background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } caption { padding: 16px; font-weight: 600; font-size: 1.1rem; color: #333; background: #f8f9fa; } th, td { padding: 14px 20px; text-align: left; border-bottom: 1px solid #eee; } th { background: steelblue; color: white; font-weight: 500; } tr:last-child td { border-bottom: none; } tr:hover td { background: #f8f9fa; }",
"sandboxCSS": "",
"initialCode": "",
"solution": "<table>\n <caption>Pricing</caption>\n <tr>\n <th>Plan</th>\n <th>Price</th>\n </tr>\n <tr>\n <td>Basic</td>\n <td>$9</td>\n </tr>\n <tr>\n <td>Pro</td>\n <td>$29</td>\n </tr>\n</table>",
"previewContainer": "preview-area",
"validations": [
{
"type": "element_exists",
"value": "table",
"message": "Add a <kbd>&lt;table&gt;</kbd> element"
},
{
"type": "element_exists",
"value": "caption",
"message": "Add a <kbd>&lt;caption&gt;</kbd> for the table title"
},
{
"type": "element_count",
"value": { "selector": "th", "min": 2 },
"message": "Add header cells (<kbd>&lt;th&gt;</kbd>) for Plan and Price"
},
{
"type": "element_count",
"value": { "selector": "tr", "min": 3 },
"message": "Add 3 rows (1 header + 2 data rows)"
}
]
},
{
"id": "table-sections",
"title": "Table Sections",
"description": "Semantic table sections improve accessibility and allow for separate styling:<br><br>• <kbd>&lt;thead&gt;</kbd> — header section<br>• <kbd>&lt;tbody&gt;</kbd> — main content<br>• <kbd>&lt;tfoot&gt;</kbd> — footer (totals, summaries)",
"task": "Wrap the header row in <kbd>&lt;thead&gt;</kbd> and data rows in <kbd>&lt;tbody&gt;</kbd>.",
"previewHTML": "",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } table { border-collapse: collapse; width: 100%; max-width: 350px; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } th, td { padding: 12px 16px; text-align: left; } thead { background: steelblue; color: white; } tbody tr:nth-child(even) { background: #f8f9fa; }",
"sandboxCSS": "",
"initialCode": "<table>\n <tr>\n <th>Name</th>\n <th>Score</th>\n </tr>\n <tr>\n <td>Alice</td>\n <td>95</td>\n </tr>\n <tr>\n <td>Bob</td>\n <td>87</td>\n </tr>\n</table>",
"solution": "<table>\n <thead>\n <tr>\n <th>Name</th>\n <th>Score</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>Alice</td>\n <td>95</td>\n </tr>\n <tr>\n <td>Bob</td>\n <td>87</td>\n </tr>\n </tbody>\n</table>",
"previewContainer": "preview-area",
"validations": [
{
"type": "element_exists",
"value": "thead",
"message": "Add a <kbd>&lt;thead&gt;</kbd> section for the header"
},
{
"type": "element_exists",
"value": "tbody",
"message": "Add a <kbd>&lt;tbody&gt;</kbd> section for the data"
}
]
},
{
"id": "table-colspan",
"title": "Spanning Columns",
"description": "The <kbd>colspan</kbd> attribute lets a cell span multiple columns. This is useful for headers that group multiple columns or footer totals.<br><br><pre>&lt;td colspan=\"2\"&gt;...&lt;/td&gt;</pre>",
"task": "Add a footer row that spans both columns using <kbd>colspan=\"2\"</kbd>.",
"previewHTML": "",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; } table { border-collapse: collapse; width: 100%; max-width: 350px; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } th, td { padding: 12px 16px; text-align: left; border-bottom: 1px solid #eee; } thead { background: steelblue; color: white; } tfoot { background: #f0f0f0; font-weight: 600; }",
"sandboxCSS": "",
"initialCode": "<table>\n <thead>\n <tr>\n <th>Item</th>\n <th>Price</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>Coffee</td>\n <td>$4</td>\n </tr>\n <tr>\n <td>Cake</td>\n <td>$6</td>\n </tr>\n </tbody>\n</table>",
"solution": "<table>\n <thead>\n <tr>\n <th>Item</th>\n <th>Price</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>Coffee</td>\n <td>$4</td>\n </tr>\n <tr>\n <td>Cake</td>\n <td>$6</td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td colspan=\"2\">Total: $10</td>\n </tr>\n </tfoot>\n</table>",
"previewContainer": "preview-area",
"validations": [
{
"type": "element_exists",
"value": "tfoot",
"message": "Add a <kbd>&lt;tfoot&gt;</kbd> section"
},
{
"type": "contains",
"value": "colspan",
"message": "Use <kbd>colspan</kbd> to span columns"
}
]
}
]
}