learning-website-framework1-4 Exercise 3: Tokens, Specificity and Load Order =================================================================================== PART A: Write tokens.css for the two neutral families ----------------------------------------------------- Values come from the real palettes found in Exercise 1. /* tokens.css — loaded by the shared layout on every site */ :root { /* language-course family */ --lang-bg: #0f1117; --lang-surface: #1a1d27; --lang-border: #2a2d3a; --lang-text: #e2e4ec; --lang-muted: #a0a4b8; /* technical-course family */ --tech-bg: #0f1117; --tech-surface: #161b22; --tech-border: #30363d; --tech-text: #c9d1d9; --tech-muted: #8b949e; } /* the family a site uses is chosen once, on the page wrapper */ [data-family="language"] { --bg: var(--lang-bg); --surface: var(--lang-surface); --border: var(--lang-border); --text: var(--lang-text); --muted: var(--lang-muted); } [data-family="technical"] { --bg: var(--tech-bg); --surface: var(--tech-surface); --border: var(--tech-border); --text: var(--tech-text); --muted: var(--tech-muted); } /* accents are per language / per site */ .hu-lesson { --accent: #5aa469; } /* Hungarian */ .de-lesson { --accent: #e0a82e; } /* German */ .jp-lesson { --accent: #d64550; } /* Japanese */ .fr-lesson { --accent: #4f8ef7; } /* French */ PART B: Who wins when shared and fragment CSS collide? ------------------------------------------------------ Save as specificity.py: import re def specificity(selector): """(ids, classes/attributes/pseudo-classes, elements) for a simple selector.""" s = re.sub(r"::?[a-z-]+\([^)]*\)", "", selector) # drop :not(...) style args for this simple version ids = len(re.findall(r"#[\w-]+", s)) classes = len(re.findall(r"\.[\w-]+|\[[^\]]+\]|:[a-z-]+", s)) s2 = re.sub(r"#[\w-]+|\.[\w-]+|\[[^\]]+\]|::?[a-z-]+", " ", s) elements = len([t for t in re.split(r"[\s>+~]+", s2) if re.match(r"^[a-zA-Z]", t)]) return (ids, classes, elements) rules = [ ".tip-box", ".lwf1-lesson .tip-box", ".hu-lesson .tip-box", "[data-site=languages] .tip-box", "div.tip-box", "#content .tip-box", ] for r in rules: print(f"{str(specificity(r)):<12} {r}") print() a, b = ".tip-box", ".hu-lesson .tip-box" print(f"{b!r} beats {a!r}: {specificity(b) > specificity(a)}") print(f"tie between '.hu-lesson .tip-box' and '[data-site=languages] .tip-box': " f"{specificity('.hu-lesson .tip-box') == specificity('[data-site=languages] .tip-box')}") Output (checked by running it): (0, 1, 0) .tip-box (0, 2, 0) .lwf1-lesson .tip-box (0, 2, 0) .hu-lesson .tip-box (0, 2, 0) [data-site=languages] .tip-box (0, 1, 1) div.tip-box (1, 1, 0) #content .tip-box '.hu-lesson .tip-box' beats '.tip-box': True tie between '.hu-lesson .tip-box' and '[data-site=languages] .tip-box': True (This calculator is deliberately simple: it ignores :not(), :is() and :where(). Browsers use the full rules.) Reading the result ------------------ - A fragment's own rule ".hu-lesson .tip-box" has higher specificity than a shared ".tip-box", so the fragment wins. That is the safe default during migration: old pages keep their look until you remove their rules. - A shared rule written as "[data-site=languages] .tip-box" TIES with the fragment's rule. On a tie, whichever comes LATER in the document wins. The layout's stylesheet link is in
; the fragment's