Meet the Variables
Values with Dynamic Superpowers
Section titled “Values with Dynamic Superpowers”Before you can cast spells, you need ingredients.
CSS custom properties (a.k.a. CSS variables) are your named ingredients.
They:
- Start with
-- - Are declared on elements like any other CSS property
- Cascade and inherit through the DOM
- Get read with the
var()function
Think: labels for values, not mini CSS files.
🔮 Declaring a Custom Property
Section titled “🔮 Declaring a Custom Property”:root { --brand-color: #ff6ec7; --card-radius: 1rem;}A custom property is just a named value stored on an element.
Putting them in :root makes them effectively “global” for the whole page
(because everything lives inside html, and :root is the html element).
You can also scope them lower:
.lesson-card { --card-radius: 1.25rem;}Inside .lesson-card, --card-radius overrides the :root value.
Outside it, the global value still wins.
🧷 Using a Custom Property with var()
Section titled “🧷 Using a Custom Property with var()”Declaring does nothing until you use it:
.card { background: var(--brand-color); border-radius: var(--card-radius);}var(--brand-color) literally means:
grab the computed value of
--brand-coloron this element (or from its cascade).
You can mix variables with normal values:
.hero { padding: 3rem var(--page-gutter);}🛟 Fallback Values (Safety Nets)
Section titled “🛟 Fallback Values (Safety Nets)”Sometimes a variable isn’t set (or gets set to something invalid).
That’s where the second argument to var() comes in:
.hero-title { color: var(--headline-color, #e5e7eb);}- If
--headline-colorexists and is valid → use it. - Otherwise → use
#e5e7eb.
You can even chain fallbacks:
color: var(--headline-color, var(--brand-color, #333));Read as:
use
--headline-color, or if that’s missing,--brand-color,
and if that fails, go with#333.
⚠️ Important: Variables Store Values, Not Properties
Section titled “⚠️ Important: Variables Store Values, Not Properties”Custom properties are not “macro expanders” for whole declarations.
They store just the value part.
Bad idea (won’t work):
:root { --fancy-border: border: 3px solid hotpink;}
.card { var(--fancy-border); /* ❌ invalid — not a full declaration */}Correct pattern:
:root { --fancy-border-width: 3px; --fancy-border-color: hotpink;}
.card { border: var(--fancy-border-width) solid var(--fancy-border-color);}Think: var() can plug values into any place a value is legal —
inside border, box-shadow, transform, font-size, etc.
🔢 Unitless Values (And Friends)
Section titled “🔢 Unitless Values (And Friends)”Custom properties don’t care about units; they store raw text.
:root { --shadow-strength: 0.35; /* unitless number */ --lift-distance: 18px; /* with unit */}
.card { box-shadow: 0 20px 40px rgba(15, 23, 42, var(--shadow-strength)); transform: translateY(calc(-1 * var(--lift-distance)));}The browser just drops the text of the variable into the value.
As long as the final result is valid CSS, you’re good.
We’ll lean on this more in the Performance Patterns section, where we coordinate multiple animations from a single “strength” variable.
🧪 MiniMo 02 — Color Cauldron
Section titled “🧪 MiniMo 02 — Color Cauldron”Tiny variables lab: one button, three knobs.
Tweak the values and watch the whole look shift.
🧪 How to play
Section titled “🧪 How to play”-
Open the page in your browser.
-
Pop open DevTools → Elements →
<style>block. -
Tweak these variables:
--btn-bg— change the brand color--btn-radius— try0.75rem,2rem,12px--btn-shadow-strength— try0.15vs0.6
One change to the variable → multiple visual changes snap into place.
💡 Demo Tie-In
Section titled “💡 Demo Tie-In”In the Meet the Variables demo, we’ll:
- Move shared values (colors, spacing, radii) into
:root - Use local overrides on specific cards/sections
- Add fallbacks for safer theme experiments
You’ll see how variables turn “copy-paste styling” into tweak-once, reuse-everywhere.
➡️ Next Up
Section titled “➡️ Next Up”Ready to aim those variables?
Next: Scope the Magic → where we control who sees which value where.