diff --git a/lessons/02-selectors.json b/lessons/02-selectors.json index 28aac6e..b64f9a4 100644 --- a/lessons/02-selectors.json +++ b/lessons/02-selectors.json @@ -17,6 +17,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "Element selectors work by matching the tag name against every node in the DOM tree. The browser traverses the entire document, checking each element's type. When it finds a match, it applies the styles. This is why p selects ALL paragraph elements—the browser doesn't stop after the first match. Element selectors have the lowest specificity (0,0,0,1), making them easy to override with classes or IDs.", + "diagram": "Browser DOM Traversal\n\n\n \n

← Check: is this a

? NO\n

← Check: is this a

? YES ✓ Apply styles\n

← Check: is this a

? NO\n

← Check: is this a

? YES ✓ Apply styles\n \n\n\nSpecificity: 0,0,0,1 (lowest)" + }, "validations": [ { "type": "contains", "value": "p {", "message": "Use the element selector p", "options": { "caseSensitive": false } }, { "type": "contains", "value": "color", "message": "Include the color property", "options": { "caseSensitive": false } }, @@ -40,6 +44,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "Class selectors match elements based on their class attribute, not their tag type. This is powerful because multiple elements of different types can share the same class. The browser checks each element's class attribute for a match—it doesn't care if it's an h2, div, or span. Class selectors have medium specificity (0,0,1,0), which is 10x higher than element selectors, allowing them to override type-based styles.", + "diagram": "Class Attribute Matching\n\n.title { color: blueviolet; }\n ↓\nBrowser searches for class=\"title\"\n ↓\n

✓ MATCH (class=\"title\")\n

✗ no class attribute\n
✓ MATCH (different type, same class!)\n\nSpecificity: 0,0,1,0\n(10x stronger than element selectors)" + }, "validations": [ { "type": "contains", @@ -67,6 +75,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "ID selectors match a single unique element by its id attribute. IDs must be unique per page, so #description can only match one element maximum. ID selectors have very high specificity (0,1,0,0)—100x stronger than class selectors! This makes IDs powerful but dangerous: their high specificity makes them hard to override later, which is why many developers prefer classes for styling.", + "diagram": "ID High Specificity\n\n#description { color: orangered; }\n ↓\nSearches for id=\"description\" (unique!)\n ↓\n
✓ MATCH (only this one)\n
✗ no id\n
✗ different id\n\nSpecificity Comparison:\n ID: 0,1,0,0 (100 points)\n Class: 0,0,1,0 (10 points)\n Element: 0,0,0,1 (1 point)\n\nID wins almost all conflicts!" + }, "validations": [ { "type": "contains", @@ -94,6 +106,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "Combining selectors creates AND logic—both conditions must be true. The selector div.note (no space between!) requires the element to be a div AND have class=\"note\". Combining also adds specificity: div.note = 0,0,1,1 (element + class), which beats .note alone = 0,0,1,0. This specificity cascade is how CSS resolves conflicts when multiple rules target the same element—higher specificity always wins.", + "diagram": "Combined Selector AND Logic\n\ndiv.note { ... }\n ↑ ↑ no space = BOTH required\n │ └─ class=\"note\"\n └───── element type
\n\n
✓ MATCH (div AND class)\n

✗ wrong element type\n

✗ missing class\n\nSpecificity Addition:\n div.note = 0,0,1,1 (11 points)\n .note = 0,0,1,0 (10 points)\n div = 0,0,0,1 (1 point)\n\nCombining selectors = higher specificity!" + }, "validations": [ { "type": "contains",