{
"$schema": "../schemas/code-crispies-module-schema.json",
"id": "html-tables",
"title": "Tables",
"description": "Create structured data tables with headers and captions",
"mode": "html",
"difficulty": "beginner",
"lessons": [
{
"id": "table-basic",
"title": "Basic Table Structure",
"description": "Tables use <table> with <tr> for rows. Inside rows, use <th> for headers and <td> for data cells.
The <caption> element provides an accessible title for the table.",
"task": "Create a simple table with:
1. A <caption> saying 'Fruit Prices'
2. A header row with 'Fruit' and 'Price' columns
3. At least 2 data rows",
"previewHTML": "",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; background: #f5f5f5; } table { border-collapse: collapse; width: 100%; max-width: 400px; background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } caption { padding: 15px; font-weight: 600; font-size: 1.2rem; color: #333; background: #f8f9fa; } th, td { padding: 12px 20px; text-align: left; border-bottom: 1px solid #eee; } th { background: #3498db; color: white; font-weight: 500; } tr:hover { background: #f8f9fa; } tr:last-child td { border-bottom: none; }",
"sandboxCSS": "",
"initialCode": "",
"solution": "
\n Fruit Prices\n \n | Fruit | \n Price | \n
\n \n | Apple | \n $1.50 | \n
\n \n | Banana | \n $0.75 | \n
\n
",
"previewContainer": "preview-area",
"validations": [
{
"type": "element_exists",
"value": "table",
"message": "Add a <table> element"
},
{
"type": "element_exists",
"value": "caption",
"message": "Add a <caption> for the table title"
},
{
"type": "element_count",
"value": { "selector": "th", "min": 2 },
"message": "Add at least 2 header cells (th)"
},
{
"type": "element_count",
"value": { "selector": "tr", "min": 3 },
"message": "Add at least 3 rows (1 header + 2 data rows)"
}
]
},
{
"id": "table-thead-tbody",
"title": "Table Head & Body",
"description": "Use <thead> to group header rows and <tbody> to group data rows. This helps browsers and assistive technology understand the table structure.
You can also use <tfoot> for footer rows like totals.",
"task": "Create a structured table:
1. A <caption> with 'Monthly Sales'
2. A <thead> with Month and Revenue headers
3. A <tbody> with at least 2 data rows",
"previewHTML": "",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; margin: 0; box-sizing: border-box; } table { border-collapse: collapse; width: 100%; max-width: 450px; background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,0.2); } caption { padding: 20px; font-weight: 700; font-size: 1.3rem; color: white; background: transparent; text-shadow: 0 2px 4px rgba(0,0,0,0.2); caption-side: top; } thead { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } th { padding: 15px 20px; text-align: left; color: white; font-weight: 500; } tbody tr { border-bottom: 1px solid #eee; } tbody tr:hover { background: #f8f9fa; } td { padding: 15px 20px; color: #333; } tbody tr:last-child { border-bottom: none; }",
"sandboxCSS": "",
"initialCode": "",
"solution": "\n Monthly Sales\n \n \n | Month | \n Revenue | \n
\n \n \n \n | January | \n $12,500 | \n
\n \n | February | \n $14,200 | \n
\n \n
",
"previewContainer": "preview-area",
"validations": [
{
"type": "element_exists",
"value": "table",
"message": "Add a <table> element"
},
{
"type": "element_exists",
"value": "caption",
"message": "Add a <caption> element"
},
{
"type": "element_exists",
"value": "thead",
"message": "Add a <thead> for the header section"
},
{
"type": "element_exists",
"value": "tbody",
"message": "Add a <tbody> for the data rows"
},
{
"type": "element_count",
"value": { "selector": "tbody tr", "min": 2 },
"message": "Add at least 2 data rows in tbody"
}
]
},
{
"id": "table-complete",
"title": "Complete Table with Footer",
"description": "Add <tfoot> to create a footer section for totals or summary data. The footer stays at the bottom even if tbody has many rows.
Combine all sections for a fully structured, accessible table.",
"task": "Create a complete table:
1. A <caption> with 'Order Summary'
2. A <thead> with Item and Price headers
3. A <tbody> with 2 items
4. A <tfoot> with a Total row",
"previewHTML": "",
"previewBaseCSS": "body { font-family: system-ui; padding: 20px; background: #fafafa; } table { border-collapse: collapse; width: 100%; max-width: 400px; background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.1); } caption { padding: 15px 20px; font-weight: 600; font-size: 1.1rem; color: #333; text-align: left; background: #f8f9fa; border-bottom: 2px solid #eee; } th, td { padding: 12px 20px; text-align: left; } thead th { background: #2c3e50; color: white; } tbody td { border-bottom: 1px solid #eee; } tbody tr:hover { background: #f8f9fa; } tfoot { background: #ecf0f1; font-weight: 600; } tfoot td { border-top: 2px solid #2c3e50; color: #2c3e50; }",
"sandboxCSS": "",
"initialCode": "",
"solution": "\n Order Summary\n \n \n | Item | \n Price | \n
\n \n \n \n | Widget | \n $25.00 | \n
\n \n | Gadget | \n $35.00 | \n
\n \n \n \n | Total | \n $60.00 | \n
\n \n
",
"previewContainer": "preview-area",
"validations": [
{
"type": "element_exists",
"value": "table",
"message": "Add a <table> element"
},
{
"type": "element_exists",
"value": "caption",
"message": "Add a <caption> element"
},
{
"type": "element_exists",
"value": "thead",
"message": "Add a <thead> section"
},
{
"type": "element_exists",
"value": "tbody",
"message": "Add a <tbody> section"
},
{
"type": "element_exists",
"value": "tfoot",
"message": "Add a <tfoot> section for the total"
},
{
"type": "element_count",
"value": { "selector": "tbody tr", "min": 2 },
"message": "Add at least 2 item rows in tbody"
}
]
}
]
}