diff --git a/lessons/00-basic-selectors.json b/lessons/00-basic-selectors.json index 915798c..818384f 100644 --- a/lessons/00-basic-selectors.json +++ b/lessons/00-basic-selectors.json @@ -18,6 +18,10 @@ "codeSuffix": "", "previewContainer": "preview-area", "solution": "p { color: blue }", + "concept": { + "explanation": "Selectors are pattern-matching rules that tell the browser which HTML elements to style. The browser scans through your HTML document's DOM tree, testing each element against your selector pattern. When an element matches, the browser applies the styles. This is why the p selector affects both paragraphs but not the h1 or div—only elements with the tag name 'p' match the pattern.", + "diagram": "HTML Document (DOM Tree)\n\n\n

Title

← p selector: NO MATCH\n

Text

← p selector: MATCH ✓\n
Box
← p selector: NO MATCH\n

More

← p selector: MATCH ✓\n\n\nResult: Only

elements get styled" + }, "validations": [ { "type": "regex", @@ -68,6 +72,10 @@ "codeSuffix": "", "previewContainer": "preview-area", "solution": "/* 1. Make h2 headings purple */\nh2 {\n color: purple;\n}\n\n/* 2. Give span elements a yellow background */\nspan {\n background-color: yellow;\n}\n\n/* 3. Make strong elements red */\nstrong {\n color: red;\n}", + "concept": { + "explanation": "Type selectors have the lowest specificity in CSS, which makes them perfect for establishing baseline styles. They cast a wide net—every element of that type gets styled. This is intentional: you set foundational styles with type selectors, then use more specific selectors (classes, IDs) to override individual elements when needed.", + "diagram": "Type Selector Specificity\n\nLow specificity = applies broadly\n\nh2 { color: purple; }\n ↓\nMatches ALL

elements\n ↓\n

First

✓ purple\n

Second

✓ purple\n

Third

✓ purple" + }, "validations": [ { "type": "regex", @@ -129,6 +137,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "Class selectors match elements by their class attribute, not their tag name. This is powerful because it lets you apply the same styles across different element types—span, p, and li can all share the highlight class. Class selectors have medium specificity, higher than type selectors, so they can override type selector rules.", + "diagram": "Class Selector Matches Attribute\n\n.highlight { ... }\n ↓\nSearches for class=\"highlight\"\n ↓\n ✓ MATCH\n

✓ MATCH\n

  • ✓ MATCH\n

    ✗ no match" + }, "validations": [ { "type": "regex", @@ -187,6 +199,10 @@ "codeSuffix": "", "previewContainer": "preview-area", "solution": ".card.featured { border-color: gold; background-color: lemonchiffon; }", + "concept": { + "explanation": "Chaining class selectors with no space between them creates an AND condition—the element must have ALL the classes to match. The selector .card.featured only matches elements with both card and featured in their class attribute. This has higher specificity than a single class, so it can override .card or .featured rules. No space between selectors is crucial—a space would mean descendant relationship instead.", + "diagram": "Chained Selectors = AND Logic\n\n.card.featured { ... }\n ↑ no space = BOTH required\n\n

    ✗ missing 'featured'\n
    ✓ has BOTH\n
    ✗ missing 'card'\n\nSpecificity: 2 classes > 1 class" + }, "validations": [ { "type": "regex", @@ -249,6 +265,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "Combining type and class selectors creates a more specific pattern that requires BOTH conditions. The selector span.highlight only matches span elements with the highlight class—not paragraphs with that class, not spans without it. This higher specificity lets you apply different styles to the same class name depending on which element type it's on, creating contextual variations.", + "diagram": "Type + Class Combination\n\nspan.highlight { ... }\n ↓\nMust be AND have class=\"highlight\"\n ↓\n ✓ MATCH\n

    ✗ wrong type\n ✗ wrong class\n\nSpecificity: type + class > class alone" + }, "validations": [ { "type": "regex", @@ -293,6 +313,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "ID selectors match a single element with a specific id attribute. Because IDs must be unique per page, #main-title will only ever match one element. IDs have very high specificity—higher than classes—so they override class and type selector rules. This makes IDs powerful but also harder to override later, which is why many developers prefer classes for reusable styles.", + "diagram": "ID Selector High Specificity\n\n#main-title { color: purple; }\n ↓\nMatches ONE element with id=\"main-title\"\n ↓\n

    ✓ MATCH (only one!)\n

    ✗ different ID\n\nSpecificity Hierarchy:\nID > class > type" + }, "validations": [ { "type": "regex", @@ -350,6 +374,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "Combining type and ID adds extra specificity and enforces a pattern—the ID must be on a specific element type. In this example, p#special has even higher specificity than #special alone. This prevents the h2 with the same ID from matching, even though IDs should be unique. This technique is useful when you want to ensure an ID only matches if it's on the correct element type.", + "diagram": "Type + ID Specificity Boost\n\np#special { ... }\n ↓\nMust match BOTH conditions:\n 1. Element type =

    \n 2. id = \"special\"\n ↓\n

    ✗ wrong type (not

    )\n

    ✓ MATCH (both pass)\n\nSpecificity: type + ID > ID alone" + }, "validations": [ { "type": "regex", @@ -395,6 +423,10 @@ "codeSuffix": "", "previewContainer": "preview-area", "solution": "p.note,\nli.important,\n#summary {\n background-color: lightyellow;\n border-left: 3px solid gold;\n padding-left: 10px;\n}", + "concept": { + "explanation": "Selector lists are a shorthand that prevents writing the same properties multiple times. The browser treats each selector in the list independently—it matches elements against each selector separately, then applies the shared styles to all matches. This is purely for convenience and doesn't create any special relationship between the selectors. Each selector maintains its own specificity.", + "diagram": "Selector List = OR Logic\n\np.note, li.important, #summary { ... }\n ↓ ↓ ↓\n Match OR Match OR Match\n ↓ ↓ ↓\n

    ✓ first matches\n

  • ✓ second matches\n
    ✓ third matches\n\nAll three get the same styles" + }, "validations": [ { "type": "contains", @@ -481,6 +513,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "The universal selector * is a wildcard that matches every element type. When used alone, it affects the entire document. When combined with a descendant selector (like div.container *), it matches all descendants—children, grandchildren, and so on—regardless of element type. The space before * indicates a descendant relationship, not a direct parent-child relationship.", + "diagram": "Universal Selector as Wildcard\n\ndiv.container * { ... }\n ↑ ↑\n context wildcard (all descendants)\n\n
    \n

    ← * matches this\n

    ← * matches this\n

      ← * matches this\n
    • ← * matches this (nested!)\n

    \n

    ← NOT inside .container, no match" + }, "validations": [ { "type": "regex", @@ -525,6 +561,10 @@ "initialCode": "", "codeSuffix": "", "previewContainer": "preview-area", + "concept": { + "explanation": "When multiple rules match the same element, CSS uses specificity to decide which wins. Think of specificity as a point system: IDs are worth 100 points, classes 10 points, elements 1 point. The selector .content p (10 + 1 = 11 points) beats p (1 point), so green wins over red. This is the cascade in action—specificity determines which styles cascade down to the element.", + "diagram": "Specificity Point System\n\nSelector | Points | Color\n------------------+--------+-------\np | 1 | red\n.content p | 11 | green ← WINS!\n#main .content p | 111 | (would win over both)\n\nHigher points = wins the cascade\n\nThe

    matches both rules, but:\n.content p has higher specificity → green" + }, "validations": [ { "type": "regex",