{
"$schema": "../schemas/code-crispies-module-schema.json",
"id": "responsive-design",
"title": "CSS Responsive Design",
"description": "Make your layouts adapt to different screen sizes using media queries and fluid design techniques.",
"difficulty": "intermediate",
"lessons": [
{
"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 .panel {\n background: lightcoral;\n }\n}",
"task": "Write a media query with @media (max-width: 600px) that changes .panel background to lightcoral.",
"previewHTML": "Fluid Typography
", "previewBaseCSS": "body { font-family: sans-serif; padding: 1rem; }", "sandboxCSS": "", "codePrefix": "/* Apply fluid font sizing */\n.text {", "initialCode": "", "codeSuffix": "}", "solution": " font-size: 5vw;", "previewContainer": "preview-area", "concept": { "explanation": "Viewport units (vw, vh, vmin, vmax) are relative units that scale proportionally with the browser window size. The vw unit means \"viewport width\"—1vw equals 1% of the viewport's width, so 5vw on a 1000px-wide screen calculates to 50px (5% of 1000px). As the user resizes the window, the browser recalculates the font size in real-time: on a 600px screen, 5vw becomes 30px; on a 1400px screen, it becomes 70px. This creates truly fluid typography that adapts smoothly without media query breakpoints. However, pure vw units can become too small on mobile or too large on wide screens, so production sites often combine vw with clamp() or calc() to set minimum and maximum bounds (e.g., clamp(16px, 5vw, 48px) keeps text readable across all devices).", "diagram": "Viewport Width Units (vw)\n\nHow 5vw calculates across screen sizes:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nMobile (375px wide):\n1vw = 375px / 100 = 3.75px\n5vw = 3.75px × 5 = 18.75px\n┌──────────┐\n│ Text │ 18.75px font\n└──────────┘\n 375px\n\nTablet (768px wide):\n1vw = 768px / 100 = 7.68px\n5vw = 7.68px × 5 = 38.4px\n┌─────────────────────┐\n│ Text │ 38.4px font\n└─────────────────────┘\n 768px\n\nDesktop (1440px wide):\n1vw = 1440px / 100 = 14.4px\n5vw = 14.4px × 5 = 72px\n┌───────────────────────────────────────┐\n│ Text │ 72px font\n└───────────────────────────────────────┘\n 1440px\n\nViewport Unit Reference:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nvw = 1% of viewport width\nvh = 1% of viewport height\nvmin = 1% of viewport's smaller dimension\nvmax = 1% of viewport's larger dimension\n\nExample with 800px × 600px viewport:\n 1vw = 8px (1% of 800px)\n 1vh = 6px (1% of 600px)\n 1vmin = 6px (1% of smaller: 600px)\n 1vmax = 8px (1% of larger: 800px)\n\nProblem: Unbounded Scaling\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nPure vw can be too small or too large:\n\nMobile (320px): font-size: 5vw → 16px ✓ OK\nTablet (768px): font-size: 5vw → 38px ✓ OK\nDesktop (2560px): font-size: 5vw → 128px ✗ TOO BIG!\n\nSolution: Combine with clamp() or calc()\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nBetter approach:\nfont-size: clamp(16px, 5vw, 48px);\n ↓ ↓ ↓\n minimum fluid maximum\n\nResult across viewports:\n320px → 5vw = 16px → clamped to 16px (min)\n768px → 5vw = 38px → 38px (in range)\n2560px → 5vw = 128px → clamped to 48px (max)\n\nWhen to Use Fluid Typography:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nGood: Hero headings, banners, display text\nAvoid: Body text, UI elements (use rem instead)", "containerVsItem": "" }, "validations": [ { "type": "property_value", "value": { "property": "font-size", "expected": "5vw" }, "message": "Set font-size: 5vw" } ] }, { "id": "responsive-3", "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": "