A Value You Define Once, Use Everywhere
A CSS custom property — often just called a "CSS variable" — stores a value under a name you choose, prefixed with two dashes. Reference it anywhere with var(), and if you ever need to change that value, you change it in exactly one place.
- ✓Custom properties are declared like --name: value; and read with var(--name).
- ✓Declaring them on :root makes them available to every element on the page.
- ✓Unlike Sass variables, custom properties are live in the browser — they can even change with media queries or JavaScript.
--name and var()
Declare a custom property on :root so it's available globally, then reference it with var() anywhere you'd normally write a literal value.
:root { --brand-orange: #e8590c; --brand-ink: #12141c; --radius-md: 12px; } .btn { background: var(--brand-orange); color: white; border-radius: var(--radius-md); } .heading { color: var(--brand-ink); }
:root targets the <html> element with slightly higher specificity — it's the conventional place to define global custom properties so they cascade down to every element on the page.
A Second Argument for var()
var() accepts an optional second argument — a fallback used if the custom property isn't defined. This is especially useful for reusable components that might be dropped into a page without every variable set up.
.chip { /* uses --custom-set if defined, else falls back to orange */ background: var(--custom-set, var(--orange)); }
Redefining a Variable Inside a Component
Custom properties follow the cascade like any other CSS. Redeclare the same variable name on a child element or a class, and everything inside that scope picks up the new value — without touching the original component's rules.
.token-card { --card-bg: #fff1e6; --card-ink: #b8430a; background: var(--card-bg); color: var(--card-ink); } /* same component, different theme — no duplicated rules */ .token-card.theme-b { --card-bg: #fff0f5; --card-ink: #c2447a; }
Default
Orange token set.
Theme B
Pink token set.
Theme C
Indigo token set.
Not the Same Thing
If you've heard of Sass or LESS variables, custom properties look similar but behave differently underneath.
Sass variables compile away before the browser sees them; CSS custom properties stay live at runtime.
Custom properties inherit and can be overridden per element, just like any other CSS property.
Custom properties can be redefined inside a media query to swap values responsively.
Build a Small, Consistent System
Breaking Down What You Just Learned
Declare and read--name: value; declares a custom property; var(--name) reads it back.
Global scopeDeclaring variables on :root makes them available to every element on the page.
Fallbacksvar(--name, fallback) supplies a backup value if the variable isn't defined.
Scoped overridesRedeclaring a variable on a class swaps its value for everything inside that scope.
Name by purposePurpose-based names like --brand-primary stay accurate even as the underlying value changes.
Try It Yourself
Take a page from earlier in the course and pull every repeated color and spacing value into :root custom properties. Then create a second "theme" class that overrides just the color variables on one section.
Build a Token-Driven Component
Practicing custom properties end to end
Create day23.html linked to a stylesheet and build the following on the page.
- Define --brand-primary, --brand-ink, and --radius-md on :root.
- Build a card component that uses all three variables via var().
- Duplicate the card and add a .theme-alt class that overrides just the color variables.
- Use var() with a fallback value on one property that isn't defined anywhere.
- Confirm changing a single :root value updates every element that references it.
Recap
--name: value; declares a variable; var(--name) reads it wherever a value is needed.
:root is the conventional place to define variables shared across the whole page.
A second argument to var() supplies a backup if the variable is undefined.
Redeclaring a variable on a class swaps its value for just that scope.
Key Takeaways
- Custom properties are declared with -- and read with var(), storing a value once for reuse everywhere.
- :root is the standard place to define variables meant to be shared across an entire page.
- var() accepts an optional fallback value as its second argument.
- Redeclaring the same variable name inside a narrower scope overrides it for that scope only — the cascade still applies.
- Unlike Sass variables, custom properties are live in the browser and can update responsively or via JavaScript.