CSS Custom Properties
Custom properties turn CSS into a system: define a value once on :root, reference it everywhere with var(), redefine it per theme or per component. They're the mechanism behind this site's entire dark mode.
1. Define, use, fallback
:root {
--brand: #5A8AB9;
--radius: 14px;
--space: 1rem;
}
.card {
background: var(--surface, #fff); /* fallback if unset */
border-radius: var(--radius);
padding: calc(var(--space) * 1.5); /* math with variables */
}Declared on :root they're global; declared anywhere else they scope to that subtree. Unlike preprocessor variables they live at runtime — JavaScript can read and write them, and calc() composes them freely.
2. Theming: the killer app
:root {
--paper: #F5F7F8;
--ink: #20242A;
}
[data-theme="dark"] {
--paper: #141A21;
--ink: #E8EDF2;
}
body { background: var(--paper); color: var(--ink); }Flip one attribute and every var() consumer updates — no duplicate stylesheets. Press the moon icon in this site's header: you're watching exactly this technique. The same scoping powers component variants: set --accent differently per card class and shared rules render differently.
3. Try it yourself
Extract the repeated blue into --brand on :root and use var(--brand) in both rules — then change the variable once to #E0594A and watch both update.
4. Quiz — check your understanding
CSS Custom Properties Quiz
4 questions · pass at 60%Q1. Custom properties are declared and read with…
Q2. Where do you declare a globally available variable?
Q3. var(--gap, 16px) — the 16px is…
Q4. Why are custom properties ideal for theming?
Every lesson quiz you pass (60%+) is saved in your browser and counts toward the CSSmatic Certificate of Completion.