From 3df98fe09a6582f7503d26de3f92c6d5e451d043 Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Sun, 11 Jan 2026 05:18:49 +0100 Subject: [PATCH] feat: Add conceptual explanations to advanced selectors Add 'concept' objects to all 4 lessons in 02-selectors.json: - Element selectors: Explain DOM traversal and specificity (0,0,0,1) - Class selectors: Explain attribute matching and medium specificity (0,0,1,0) - ID selectors: Explain uniqueness and high specificity (0,1,0,0) - Combined selectors: Explain AND logic and specificity addition Each concept includes: - Beginner-friendly explanation (2-4 sentences) - ASCII diagram showing how selectors match - Specificity comparison and cascade behavior Subtask 3.5 - Advanced selectors conceptual explanations --- lessons/02-selectors.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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",