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
\nText
← p selector: MATCH ✓\nMore
← p selector: MATCH ✓\n\n\nResult: Onlyelements 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
✓ 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
✗ 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 \n 2. id = \"special\"\n ↓\n )\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 ← * matches this\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",
✓ 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 =
✗ wrong type (not
← * matches this\n
← * matches this\n