Fresh Roasted Coffee
\nOur beans are sourced from small farms in Colombia and Ethiopia.
\nEach batch is roasted weekly to ensure peak freshness.
\n{
"$schema": "../schemas/code-crispies-module-schema.json",
"id": "css-basic-selectors",
"title": "CSS Basics",
"description": "Learn the fundamental building blocks of CSS: properties, values, and selectors. This module teaches you the syntax rules that every CSS declaration follows.",
"difficulty": "beginner",
"lessons": [
{
"id": "css-properties",
"title": "CSS Properties",
"description": "CSS styles elements using declarations - pairs of properties and values. Every declaration follows the same pattern:
property: value;
This text should turn coral.
", "previewBaseCSS": "body { font-family: system-ui; padding: 20px; } .text { font-size: 1.25rem; }", "sandboxCSS": "", "codePrefix": ".text {\n ", "initialCode": "", "codeSuffix": "\n}", "previewContainer": "preview-area", "solution": "color: coral;", "validations": [ { "type": "property_value", "value": { "property": "color", "expected": "coral" }, "message": "Add color: coral;" } ] }, { "id": "multiple-properties", "title": "Multiple Properties", "description": "A rule can have multiple declarations. Each one goes on its own line, and each needs a semicolon at the end:.box {
background: gold;
color: navy;
padding: 1rem;
}p {
color: steelblue;
}Our beans are sourced from small farms in Colombia and Ethiopia.
\nEach batch is roasted weekly to ensure peak freshness.
\n.badge {
background: coral;
}You have new notifications waiting.
", "previewBaseCSS": "body { font-family: system-ui; padding: 1rem; } header { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1rem; } h1 { margin: 0; font-size: 1.5rem; } .badge { color: white; padding: 0.25rem 0.5rem; border-radius: 999px; font-size: 0.875rem; } p { color: #555; margin: 0; }", "sandboxCSS": "", "codePrefix": "", "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", "solution": ".badge {\n background: tomato;\n}", "validations": [ { "type": "regex", "value": "\\.badge\\s*\\{", "message": "Start with .badge { (don't forget the dot!)" }, { "type": "property_value", "value": { "property": "background", "expected": "tomato" }, "message": "Set background: tomato" } ] }, { "id": "button-variants", "title": "Button Variants", "description": "Elements can have multiple classes. When you chain class selectors without spaces, you target elements that have all those classes:.btn.primary {
background: steelblue;
}a.btn {
text-decoration: none;
}h1, h2, h3 {
color: steelblue;
}Introduction paragraph with some text.
More content here.
Final paragraph.
.nav a {
color: white;
}Read more in our documentation.
", "previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; margin: 0; } .nav { background: steelblue; padding: 1rem; display: flex; gap: 1rem; border-radius: 8px; margin-bottom: 1rem; } .nav a { text-decoration: none; } p a { color: steelblue; }", "sandboxCSS": "", "codePrefix": "", "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", "solution": ".nav a {\n color: white;\n}", "validations": [ { "type": "regex", "value": "\\.nav\\s+a\\s*\\{", "message": "Use .nav a { (space between .nav and a)" }, { "type": "property_value", "value": { "property": "color", "expected": "white" }, "message": "Set color: white" } ] }, { "id": "nested-styling", "title": "Nested Styling", "description": "Descendant selectors let you create contextual styles. The same element can look different depending on where it appears.This is a regular article paragraph with normal-sized text for comfortable reading.
Card paragraphs should be slightly smaller to fit the compact design.
Back to regular article text here.